前言
在没有引入viewmodels的kt内联方法之前,创建ViewModel目前常见的做法是在ViewModelStoreOwner内创建ViewModelProvider对象,再去get目标类.现在我们可以以一个完全新接触的视角,从构造方法开始去一点点拓宽了解ViewModel库的体系内容.
- ViewModelStoreOwner,我知道,Activity跟Fragment这些嘛,但更多的呢,又好像说不上来
- ViewModelStore里面长什么样
- 为什么这里用到了Factory,还是default的,那不default的是什么
- 同样的,旁边的CreationExtras也有同问
ViewModelProvider
避不开的这个类,类的介绍告知:为作用域提供VM对象的类
ViewModelStoreOwner和ViewModelStore
接口,提供getViewModelStore抽象方法实现ViewModelStore对象。androidx.activity.ComponentActivity和Fragment都实现了该接口方法。
-
ComponentActivity从NonConfigurationInstances取,如果没有再new出一个.
-
Fragment:从FragmentManager取(本质找FragmentManagerViewModel取),new出一个对象
但这里还是不知道这ViewModelStore到底里面是怎样?点开源码
可以把ViewModelStore当成是一个对map进行操作的类,map里面以String为key,val为ViewModel.从put,get,clear等方法进行操作.只是ViewModelStore作为ViewModelStoreOwner实现类里的必有字段.
从ViewModelProvider的构造方法开始
最简单的api,传个ViewModelStoreOwner进来就行,反正这年头用的不是Fragment就是ComponentActivity对吧.
defaultFactory
借助defaultFactory方法来获取Factory:
- 如果ViewModelStoreOwner还是HasDefaultViewModelProviderFactory的实现类的话,将使用ViewModelStoreOwner自有的factory,如ComponentActivity跟Fragment.
- 否则将使用内置的Factory.
好的,一个新疑问产生:什么是HasDefaultViewModelProviderFactory?
defaultCreationExtras
也是和一样defaultFactory方法执行时都套路:ViewModelStoreOwner还是HasDefaultViewModelProviderFactory的实现类的话,将使用ViewModelStoreOwner自有的CreationExtras.
- 查看得知
- 默认是CreationExtras.Empty,也就是空
可以把CreationExtras就当作是map的包装对象.
但HasDefaultViewModelProviderFactory,到底是什么?
HasDefaultViewModelProviderFactory
原来是接口.那哪些类实现了HasDefaultViewModelProviderFactory接口呢?查看继承树,如下图所示:
原来ComponentActivity跟Fragment作为ViewModelStoreOwner同时,也对HasDefaultViewModelProviderFactory接口进行了实现.
-
ComponentActivity:ComponentActivity用的Factory是SavedStateViewModelFactory,赋值给
mDefaultFactory字段,借助其create方法完成对ViewModel的创建 -
Fragment:最终也是用SavedStateViewModelFactory,赋值给
mDefaultFactory字段
这里出现了ViewModelProvider.Factory,他们之间有什么联系.我们从类信息入手
ViewModelProvider.Factory
注释说得清楚,其职责就是用于初始化ViewModel.这里有两个抽象方法用于具体返回ViewModel实例的.右边看到实现类,关于实例类的内容,待会我们带着问题继续看.
内置Factory:
NewInstanceFactory
构造函数点击defaultFactory方法,排除实现了HasDefaultViewModelProviderFactory接口的ViewModelStoreOwner类,后默认使用NewInstanceFactory,对Factory接口的create实现为反射传入类的无参构造函数,创建类对象.
AndroidViewModelFactory
NewInstanceFactory子类.
create方法判断是否AndroidViewModel的子类
决定使用目标ViewModel(Application),还是父类处理的使用无参构造函数
代理Factory:SavedStateViewModelFactory(ComponentActivity和Fragment依赖的Factory)
类信息和构造方法
不光实现了ViewModelProvider.Factory接口,还实现了ViewModelProvider.OnRequeryFactory接口
意外发现,该类内部又有了一个Factory类型属性factory,将根据application==null决定使用ViewModelProvider.AndroidViewModelFactory的有参或者无参构造方法来创建
这里会开始多个疑问,为什么自己都已经是Factory实现类,为什么又要有一个factory的字段,那什么时候用,毕竟我们已经要实现create方法了不是么?
create(modelClass: Class<T>, extras: CreationExtras): T
由于ViewModelProvider的get方法里,将key作为内容塞入了CreationExtras中,并传给ViewModelProvider的factory属性的create方法,所以SavedStateViewModelFactory执行到这里的时候取出指定的key是能拿到的.
判断CreationExtras指定key是否有效,无效则走create(key: String, modelClass: Class<T>): T方法
有效情况下,判断是否作为AndroidViewModel子类,且当前SavedStateViewModelFactory的application字段是否有效:
-
是就查找目标ViewModel的(Application, SavedStateHandle) 的带参构造函数
-
不满足就查找ViewModel(SavedStateHandle) 的带参构造函数
如果目标ViewModel未定义上述的带参构造函数,就使用factory的普通create方法(具体create执行逻辑,是AndroidViewModelFactory或者父类NewInstanceFactory的create实现,根据application对象是否为空决定,参考上述ViewModelProvider.AndroidViewModelFactory)
以ComponentActivity为例子,ComponentActivity在实现HasDefaultViewModelProviderFactory接口是,对defaultViewModelCreationExtras重写,塞入其他内容
可以认为ComponentActivity执行的是上半部分,但是Fragment没有重写,取不到值,将执行下半部分,调用了create(key: String, modelClass: Class<T>): T方法.
create(key: String, modelClass: Class<T>): T
同样是根据判断ViewModel类型,查找所用的带参构造函数
判断目标ViewModel是否属于AndroidViewModel类型,且判断application字段是否为空.决定查找目标ViewModel的(Application, SavedStateHandle) 还是目标ViewModel的(SavedStateHandle)
查找构造函数结果,目标的ViewModel存在指定参数的构造函数去反射创建对象,为空情况使用类名调用create方法:
- 使用factory(如AndroidViewModelFactory)
- instance(NewInstanceFactory类)的create方法
好的,现在知道create都干了什么事,那create方法什么时候用呢?ViewModelProvider的get方法.
结论
在ComponentActivity跟Fragment会使用SavedStateViewModelFactory作为管理对象,对于前面提到的为什么又包了层Factory,其实就是代理模式里的静态代理实现.
执行create方法时,根据Application参数的是否为null,以及目标ViewModel类所声明构造函数的参数列表来决定:
对于继承自AndroidViewModel的ViewModel类,将按照如下的构造方法顺序查找并反射对象: 1. (Application, SavedStateHandle) 2. (SavedStateHandle) 3. (application: Application) 4. 无参构造
无参构造将作为兜底的方式来实现
Factory的优先级上:
- AndroidViewModelFactory(如果需要Application或者SavedStateHandle)
- NewInstanceFactory(无参)
ViewModelStore和CreationExtras就当作是个map的管理对象,只是一个管理的是ViewModel实例,一个是存key