ViewModel如何产生的?
通常我们第一步都是通过ViewModelProviders.of()
这个工具方法进行传入activity来获得。我们直接看源码
传入FragmentActivity
1 | public static ViewModelProvider of(@NonNull FragmentActivity activity) { |
走到重载方法
1 | public static ViewModelProvider of(@NonNull FragmentActivity activity, |
这两个方法区别就是有无提供工厂,其实实际上ViewModel
的生成就是工厂生产出来的。这里的话如果不提供工厂则会给我们一个默认的工厂。最后构建一个ViewModelProvider
1 | public static AndroidViewModelFactory getInstance(@NonNull Application application) { |
默认工厂也很简单就是一个AndroidViewModelFactory
实例
我们回头看ViewModelProvider
的构造方法
1 | public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) { |
传入一个ViewModelStore
和Factory
。这个ViewModelStore
看名字就是实际存储用于存储ViewModel
的。而它也是直接从FragmentActivity.getViewModelStore()
获得。
目前我们就获得到了一个activity的ViewModelProvider
。它维持了一个Factory
和ViewModelStore
,分别用于生产ViewModel
和存储ViewModel
下一步,获取具体的ViewModel
,ViewModelProvider.get(clazz)
1 | public <T extends ViewModel> T get(@NonNull Class<T> modelClass) { |
通过key获取
1 | public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) { |
看到这里就很明确了,首先直接取ViewModelStore
中通过key查找ViewModel
,查找到了且类型正确就返回。不存则通过工厂进行创建,并且放入ViewModelStore
中,这样就完成一个拿去ViewModel
。
然后看下ViewModelStore
的实现,一个很简单的HashMap
存储
1 | public class ViewModelStore { |
看下工厂
1 | public static class NewInstanceFactory implements Factory { |
这里调下默认最简单的工厂,就是直接反射创建实例,而AndroidViewModelFactory
是它的子类,只是多了一个传入Application
参数的功能,其它都没什么。
走到这里也大概明白的ViewModel
的创建。我们平时使用中两个fragment
可以共享activity
的viewmodel
,也正式因为通过activity
的ViewModelStore
进行获取的,也就完成了ViewModel
局部单例的效果。这个效果基本上是靠ViewModelProvider(xxx.getViewModelStore(), factory)
传入不同的ViewModelStore
完成的。
一个activity可以有多个fragment,通过设置activity的ViewModelStore
完成局部单例viewmdoel
。换句话说只要设置是同一个ViewModelStore
在这个范围就是单例的。Fragment的ViewModelStore则是实际来源于FragmentManager的。
全局单例ViewModel
有这样的场景,有一个view数据基本在全局都会使用的到,这个时候我们就要实现一个全局的ViewModel
,这个时候我们可以让Application来实现ViewModelStoreOwner
提供出一个全局的ViewModelStore
来存储全局的ViewModel
,工厂的可以直接使用默认的实现。
自定义工厂
我们每个ViewModel一般来说都会有可能依赖数据仓库,数据仓库我们当然是希望是全局的单例,这个时候我们就要手动取实现工厂来构建。甚至会有其它的自定义参数,这个时候也是需要自定义工厂的。
1 | class ViewModelFactory private constructor(private val dataRepository: DataRepository) : |