ViewModel
参考:https://blog.csdn.net/u010072711/article/details/80035276
创建
val viewModelProvider = ViewModelProviders.of(_mActivity,viewModelFactory) val manageViewModel = viewModelProvider.get(ManageViewModel::class.java)
源码分析ViewModel创建流程
查看ViewModelProviders类
/** * * @param activity * @param factory 提供了自定义创建ViewModel的方法 * @return */ @NonNull @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity, @NonNull ViewModelProvider.Factory factory) { //检测activity checkApplication(activity); return new ViewModelProvider(ViewModelStores.of(activity), factory); }
-
存在是依赖
Activity
或者Fragment
的,不管你在什么地方获取ViewModel
,只要你用的是相同的Activity
或者Fragment
,那么获取到的ViewModel
将是同一个 (前提是key
值是一样的),所以ViewModel
也具有数据共享的作用! -
每次获取ViewModel都是重新new ViewModelProvider
第一个参数ViewModelStores.of(activity)
@MainThread public static ViewModelStore of(@NonNull FragmentActivity activity) { //如果你的Activity实现了ViewModelStoreOwner接口具备了提供 //ViewModelStore 的功能就直接获取返回,通常我们的Activity都不会去实现这个功能 if (activity instanceof ViewModelStoreOwner) { return ((ViewModelStoreOwner) activity).getViewModelStore(); } //系统为你的Activity添加一个具有提供ViewModelStore 的holderFragment return holderFragmentFor(activity).getViewModelStore(); }
如果你的Activity实现了ViewModelStoreOwner接口具备了提供ViewModelStore 的功能就直接获取返回,通常我们的Activity都不会去实现这个功能;如果没有,则系统为你的Activity添加一个具有提供ViewModelStore 的holderFragment
总结:最终每一个Activity或者Fragment都有一个ViewModelStore,而这个ViewModelStore是存储ViewModel的
第二个参数factory,下面是自定义的ViewModelFactory kotlin写法
@Singleton class ViewModelFactory @Inject constructor( private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>> ) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { val creator = creators[modelClass] ?: creators.entries.firstOrNull { modelClass.isAssignableFrom(it.key) }?.value ?: throw IllegalArgumentException("unknown model class $modelClass") try { @Suppress("UNCHECKED_CAST") return creator.get() as T } catch (e: Exception) { throw RuntimeException(e) } } }
-
实现 ViewModelProvider.Factory,
-
构造传入Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
-
create方法根据Class,从map中获取Provider<ViewModel>,再从Provider<ViewModel>中get得到ViewModel
解析viewModelProvider.get(ManageViewModel::class.java)
@NonNull @MainThread public <T extends ViewModel> T get(@NonNull Class<T> modelClass) { String canonicalName = modelClass.getCanonicalName(); if (canonicalName == null) { throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels"); } return get(DEFAULT_KEY + ":" + canonicalName, modelClass); } @NonNull @MainThread public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) { ViewModel viewModel = mViewModelStore.get(key); if (modelClass.isInstance(viewModel)) { //noinspection unchecked return (T) viewModel; } else { //noinspection StatementWithEmptyBody if (viewModel != null) { // TODO: log a warning. } } viewModel = mFactory.create(modelClass); mViewModelStore.put(key, viewModel); //noinspection unchecked return (T) viewModel; }
流程是:
-
先从
mViewModelStore
中使用key去获取ViewModel
,mViewModelStore
中是使用HashMap
去存储一个Activity
或者Fragment
的ViewModel
的。如果获取到就返回 -
没获取到就使用单例
mFactory
的create方法反射创建ViewModel
,create方法的代码在上面贴出来了。 -
使用Key存入
mViewModelStore
并返回
解析ViewModelStore
public class ViewModelStore { private final HashMap<String, ViewModel> mMap = new HashMap<>(); final void put(String key, ViewModel viewModel) { ViewModel oldViewModel = mMap.put(key, viewModel); if (oldViewModel != null) { oldViewModel.onCleared(); } } final ViewModel get(String key) { return mMap.get(key); } /** * Clears internal storage and notifies ViewModels that they are no longer used. */ public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } }
大概内容是:
一个 HashMap
用存储ViewModel。提供get
,put
,clear
三个方法。 上面说了ViewModelStore
是每一个Activity
或者ViewModel
都有一个的,当Activity
或者Fragment
销毁的时候就会调用clear
方法了。
-
ViewModelStore被
HolderFragment
创建和持有 -
当我们要给Activity或者Fragment创建ViewModel的时候,系统就会为Activity或者Fragment添加一个
HolderFragment
,HolderFragment
中会创建持有一个ViewModelStore
结合Dagger2
@Binds @IntoMap @ViewModelKey(HealthViewModel::class) abstract fun bindHealthViewModel(healthViewModel: HealthViewModel): ViewModel @Binds @IntoMap @ViewModelKey(MainViewModel::class) abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel @Binds abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
-
@Bind 和 @Provider的作用相差不大,区别在于@Provider需要写明具体的实现,而@Binds只是告诉Dagger2谁是谁实现的
-
@IntoMap 则可以让Dagger2将多个元素依赖注入到Map之中
-
@ViewModelKey(MainViewModel::class) Dagger2会根据这些信息自动生成一个关键的Map。key为ViewModel的Class,value则为提供ViewModel实例的Provider对象,通过
provider.get()
方法就可以获取到相应的ViewModel对象
上面ViewModelFactory的分析有,看到他的构造是map,而通过dagger2 的@IntoMap @ViewModelKey()可生成一个map,正好为ViewModelFactory的创建提供参数,同时发现在ViewModelProviders.of(this)中发现默认的factory每次传入都是单例的,所以在ViewModelFactory用@Singleton来修饰
总结ViewModel的创建流程是
-
new ViewModelProvider,传入两个参数,一个是ViewModelStore,一个是ViewModelProvider.Factory,
-
ViewModelStore由,当要给Activity或者Fragment创建ViewModel的时候,系统就会为Activity或者Fragment添加一个
HolderFragment
,HolderFragment
中会创建持有一个ViewModelStore
-
当ViewModelProvider.get()时,先查看ViewModelStore是否存储有,有则返回,无则通过Factory来创建一个