Android Jetpack架构组件 ViewModel详解
前言
前面两篇文章我们已经学习了lifecycle和databind,本篇文章我们来学习jetpack系列中比较重要的viewmodel,jetpack的很多很多组件都是搭配使用的,所以单独的知识点可能会有些”无意义“但却是我们项目实战的基础!
viewmodel的使用
viewmodel类旨在以注重生命周期的方式存储和管理界面相关的数据。viewmodel类让数据可在发生屏幕旋转等配置更改后继续存在。这句话很好理解,还记得我们在讲解lifecycle的时候 举的例子吗,我们还是使用那个例子,如果你还没看过,可移步至:
android jetpack系列之lifecycle
我们再回顾一次需求:
在activity 可见的时候,我们去做一个计数功能,每隔一秒 将计数加1 ,当activity不可见的时候停止计数,当activity被销毁的时候 将计数置为0,这里我们在activity被销毁的时候不再将count置为0,workutil代码如下所示:
public class workutil implements lifecycleobserver { private static final string tag = "workutil"; private boolean whethertocount = true; private int count = 0; @onlifecycleevent(lifecycle.event.on_resume) public void start() { new thread(new runnable() { @override public void run() { while (whethertocount) { try { thread.sleep(1000); count++; log.d(tag, "start: " + count); } catch (interruptedexception e) { e.printstacktrace(); } } } }).start(); } @onlifecycleevent(lifecycle.event.on_stop) public void onstop() { whethertocount = false; log.d(tag, "onstop: "); } @onlifecycleevent(lifecycle.event.on_destroy) public void ondestory() { } }
我们运行程序,在计数的过程中 使屏幕旋转,运行结果如下所示:
我们可以看到,当屏幕旋转的时候,由于生命周期发生了改变,导致数据被销毁,所以计数器的计数又从初始值开始计数了,那么我们如何解决这个问题呢,你肯定会说,缓存呀,重写onsabeinstancestate()方法等等,都可以但是都不够优雅,那么如何优雅的来解决这个问题呢,这就是我们的今天的主角 viewmodel。
viewmodel的使用
我们新建main3activitymodel 继承自 viewmodel,在main3activitymodel中定义count变量 如下所示:
public class main3activityviewmodel extends viewmodel { public int count = 0; }
没错,就是这么简单,我们只要保证计数的变量是这个model中的变量,就可以解决我们上面的问题
我们通过viewmodelproviders来获取viewmodel对象
main3activityviewmodel = viewmodelproviders.of(this).get(main3activityviewmodel.class);
但是这个方法已经过时了,替代方法是
main3activityviewmodel = new viewmodelprovider(this).get(main3activityviewmodel.class);
为了让workutil使用model中的变量,所以我们要将viewmodel 传递过去,在workutil中新增一个构造方法
private main3activityviewmodel main3activityviewmodel; public workutil(main3activityviewmodel main3activityviewmodel) { this.main3activityviewmodel = main3activityviewmodel; }
我们将workutil中的计数变量count 改为 main3activityviewmodel.count,如下所示:
@onlifecycleevent(lifecycle.event.on_resume) public void start() { new thread(new runnable() { @override public void run() { while (whethertocount) { try { thread.sleep(1000); main3activityviewmodel.count++; log.d(tag, "start: " + main3activityviewmodel.count); } catch (interruptedexception e) { e.printstacktrace(); } } } }).start(); }
main3activity中在lifecycle中传参:
getlifecycle().addobserver(new workutil(main3activityviewmodel));
再次运行程序,运行过程中旋转手机屏幕,打印如下所示:
我们可以看到,在屏幕旋转之后,计数器的计数保留了,那么viewmodel是如何做到的呢,这是因为viewmodel 对象存在的时间比视图或 lifecycleowners 的特定实例存在的时间更长,viewmodel的生命周期如下图所示(摘自官网)
向viewmodel传参
当前计数的需求是从0开始计时,我们现在修改需求如下,使用用户输入的数字为起点开始计数,这样的话viewmodel中的count就不是0了,而是传入的参数,我们在main3activity中定义变量inputcount 来模拟用户输入的数字
private int inputcount = 100;
在main3viewmodel中添加构造方法
public int count = 0; public main3activityviewmodel(int count) { this.count = count; }
看到这里,你可能会说,我们直接new一个传过去不就行了吗,请记住这是万万不行的,因为如果我们使用直接实例化来创建viewmodel,那么viewmodel的生命周期就受activity的影响了,所以为什么我们只能通过viewmodelprovider来获取viewmodel的实例。
我们需要借助viewmodelprovider.factory来实现传参,新建main3activityviewmodelfactor继承自 viewmodelprovider.factory,重写其oncreate方法,如下所示:
public class main3activityviewmodelfactory implements viewmodelprovider.factory { @nonnull @override public <t extends viewmodel> t create(@nonnull class<t> modelclass) { return null; } }
添加一个构造方法,并在create中创建videmodel实例
private int count; public main3activityviewmodelfactory(int count) { this.count = count; } @nonnull @override public <t extends viewmodel> t create(@nonnull class<t> modelclass) { return (t) new main3activityviewmodel(count); }
在activity中获取实例的时候 采用如下方法
main3activityviewmodel = new viewmodelprovider(this,new main3activityviewmodelfactory(inputcount)).get(main3activityviewmodel.class);
运行程序,打印结果如下所示:
如此一来 我们就实现viewmodel传递参数了~
以上就是android jetpack架构组件 viewmodel详解的详细内容,更多关于android jetpack架构组件 viewmodel的资料请关注其它相关文章!