Android Jetpack架构组件之ViewModel原理篇

上一篇文章讲了viewmodel的简单使用

Android Jetpack架构组件之ViewModel使用篇

一、ViewModel

ViewModel是Jetpack AAC的重要组件,同时也有一个同名抽象类。 ViewModel,意为 视图模型,即为界面准备数据的模型。简单理解就是,ViewModel为UI层提供数据。独立的看ViewModel没有什么实际意义,更像是数据容器,结合LiveData使用更容易理解。

二、ViewModel的好处

1、Activity配置更改重建时(比如屏幕旋转)保留数据;

2、UI组件(Activity与Fragment、Fragment与Fragment)间实现数据共享。

        对于第一条不用VM的情况下只能通过onSaveInstanceState保存数据,当activity重建后再通过onCreateonRestoreInstanceState方法的bundle中取出,但如果数据量较大,数据的序列化和反序列化将产生一定的性能开销。

        对于第二条如果不用VM,各个UI组件都要持有共享数据的引用,这会带来两个麻烦,第一,如果新增了共享数据,各个UI组件需要再次声明并初始化新增的共享数据;第二,某个UI组件对共享数据修改,无法直接通知其他UI组件,需手动实现观察者模式。而VM结合LiveData就可以很轻松的实现这一点。

LiveData作为数据变化的驱动器,VM借助它可以写出十分简洁的MVVM代码。

        接下来我们来看一下VM到底是如何实现上述需求的,而事实上核心可以转化为下面两个问题。

三、ViewModel的原理(以  “翻转屏幕”  更改屏幕配置为例讲解)

        当屏幕发生翻转时,Activity的onRetainCustomNonConfigurationInstance()方法会被调用,另一个getLastNonConfigurationInstance也会被执行,上面这个方法会有机会调到下面这个get的方法。

 运行验证:

 

 系统调用到这两个API,ViewModel就是利用这两个API来完成数据的保存和恢复的。

从代码使用来寻找原理:

ViewModelProviders.of(this).get(WeatherViewModel.class);

1、先看of方法,进去发现会走到

new ViewModelProvider(activity.getViewModelStore(), (Factory)factory)

new了一个ViewModelProvider;这里发现第一个参数为获取ViewModelStore,接着看从哪获取的

 发现是在ComponentActivity上的;接着看这个ViewModelStore是什么东西

 当上面的getViewModelStore第一次执行的时候mViewModelStore == null,就回去NonConfigurationInstances这个对象上找viewmodelStore(NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();),接着进去getLastNonConfigurationInstance这个方法看看:

 第一次进来这个mLastNonConfigurationInstances变量也是为空,所以这个方法第一次返回null,

 

 所以第一次调用ViewModelProviders.of方法的时候,实际就是去初始化一个ViewModelStore,这就完成了第一步初始化一个存储viewmodel的集合ViewModelStore。

2、接着看使用时候的.get(WeatherViewModel.class),点进去看

  会走:return this.get("androidx.lifecycle.ViewModelProvider.DefaultKey:" + canonicalName, modelClass);这里用一个字符串拼接我们写的ViewModel的类名作为key,viewmodel实例作为value存储起来。(默认创建viewmodel实例的factory利用的反射的方式)

 

 以上的1,2两步就是第一次使用viewmodel的时候of负责创建viewmodelStore,get负责创建viewmodel实例并存到viewmodelStore中。那么这个和屏幕的翻转配置发生变更有什么关联呢?

 3、继续回到上面说的两个API中:onRetainCustomNonConfigurationInstance,getLastNonConfigurationInstance

当竖屏切到横屏时,先走onRetainCustomNonConfigurationInstance保存配置的方法,跟进去看

注意这里的这个nci类是 CompoentActivity的静态内部类,等下和下面的这个nc不一样的,下面的这个nc是Activity的静态内部类。但是这个onRetainNonConfigurationInstance方法是被Activity的retainNonConfigurationInstances调用

 

 好了,到这里为止,就是我们翻转屏幕改变配置的时候走的这个方法onRetainCustomNonConfigurationInstance完成的一些工作。

我们知道当屏幕翻转的时候是会重新走activity的生命周期的,所有的变量也会没值了,就又会走到这个方法的viewmodel的创建过程

 这个时候会走of的activity的getViewModelStore这个方法

 因为:下面这两个都是Activity.java 的方法,这样就对应起来了。

 而上面Activity的retainNonConfigurationInstances()方法是底层AMS调用的。只要activity没有完全销毁,这个就会存在内存中。

最后一个问题,viewmodelStore上面时候清除数据:CompoentActivity构造方法的一段代码

 我们的activity的销毁onDestory是有两种情况,正常退出或者配置发生变更有可能会(如翻转屏幕)

四、总结

 viewmodel的源码就是以上,可能会有点乱,我会重新梳理一遍的。今天国庆节,国庆节快乐!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值