Android 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的生命周期如下图所示(摘自官网)

600

向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方法,如下所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值