上一篇文章讲了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重建后再通过onCreate
或onRestoreInstanceState
方法的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的源码就是以上,可能会有点乱,我会重新梳理一遍的。今天国庆节,国庆节快乐!