本篇主要关注 ViewModel
的实现而非其用法,关于他的用法,可以参考这里 。
ViewModel
主要用于在 activity/fragment 被自动销毁时保存一些数据。从实现原理上讲,主要就是利用了 fragment.setRetainInstance(true)
。如此一来,这个 fragment
就能够跨越 activity
的生命周期。
以下源码使用 1.1.1 版本
总览
ViewModel
:这个是我们的主角。我们定义的 model 类需要继承它。
ViewModelProvider
:用于生成 ViewModel
实例
ViewModelStore
:跟他的名字一样,主要用来存储 ViewModel
的实例。
HolderFragment
:这个就是我们上面提到的调用了 setRetainInstance(true)
的那个 fragment
。ViewModelStore
实例存储会在这里。
下面是 Google 给出的示例 step2 中的一段代码:
1 2 ChronometerViewModel chronometerViewModel = ViewModelProviders.of(this ).get(ChronometerViewModel.class);
下面我们就根据这个调用来学习 ViewModel
的源码。
ViewModel 前面我们说过,自己定义的 model 类需要继承它。这里借花献佛,我们直接看 Google 的 sample:
1 2 3 public class ChronometerViewModel extends ViewModel { }
ViewModel
虽然是主角,但他非常的简单:
1 2 3 4 public abstract class ViewModel { protected void onCleared () { } }
就这样,他只是定义了一个空方法 onCleared()
。当对应的 model 实例被销毁时,onCleared()
将会执行。通过让他成为 abstract class
并给予 onCleared
一个默认实现,让 ViewModel
有了 tag interface 的效果。
所谓的 tag interface 是指不带任何方法的 interface
。
接下来是男二号 AndroidViewModel
:
1 2 3 4 5 6 7 8 9 10 11 12 public class AndroidViewModel extends ViewModel { private Application mApplication; public AndroidViewModel (@NonNull Application application) { mApplication = application; } @NonNull public <T extends Application> T getApplication () { return (T) mApplication; } }
没有太多可圈可点的东西,我们继续看下一个。
ViewModelProvider 1 2 ChronometerViewModel chronometerViewModel = ViewModelProviders.of(this ).get(ChronometerViewModel.class);
我们继续从这个调用往下看。
ViewModelProviders
可以看成是 ViewModelProvider
的工厂或相关工具类的合集。他的命名跟 JDK 里的 Collections/Arrays
类似。这里的 this
是 FragmentActivity
,所以接下来执行的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class ViewModelProviders { @NonNull @MainThread public static ViewModelProvider of (@NonNull FragmentActivity activity) { return of(activity, null ); } @NonNull @MainThread public static ViewModelProvider of (@NonNull FragmentActivity activity, @Nullable Factory factory) { Application application = checkApplication(activity); if (factory == null ) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(ViewModelStores.of(activity), factory); } }
可以看到,最终 ViewModelProviders
会创建一个 ViewModelProvider
实例并返回。
Factory
是用于创建 model 实例的工厂:
1 2 3 4 public interface Factory { @NonNull <T extends ViewModel> T create (@NonNull Class<T> modelClass) ; }
默认的实现是 AndroidViewModelFactory
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public static class AndroidViewModelFactory extends ViewModelProvider .NewInstanceFactory { private static AndroidViewModelFactory sInstance; @NonNull public static AndroidViewModelFactory getInstance (@NonNull Application application) { if (sInstance == null ) { sInstance = new AndroidViewModelFactory(application); } return sInstance; } @NonNull @Override public <T extends ViewModel> T create (@NonNull Class<T> modelClass) { if (AndroidViewModel.class.isAssignableFrom(modelClass)) { try { return modelClass.getConstructor(Application.class).newInstance(mApplication); } catch (NoSuchMethodException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (InstantiationException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (InvocationTargetException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } return super .create(modelClass); } }
父类 NewInstanceFactory
的实现一样很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static class NewInstanceFactory implements Factory { @SuppressWarnings ("ClassNewInstance" ) @NonNull @Override public <T extends ViewModel> T create (@NonNull Class<T> modelClass) { try { return modelClass.newInstance(); } catch (InstantiationException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } }
从这里可以看出,使用默认的 Factory
实现时,如果 model 类继承 ViewModel
,需要有一个默认构造函数;如果继承 AndroidViewModel
,必须有一个以 Application
为唯一参数构造函数。否则,我们需要自己实现一个 Factory
。
我们先把 ViewModelStore
放一放,先假设成功拿到了他的实例,于是,我们创建 ViewModelProvider
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static ViewModelProvider of (@NonNull FragmentActivity activity, @Nullable Factory factory) { return new ViewModelProvider(ViewModelStores.of(activity), factory); } public class ViewModelProvider { public ViewModelProvider (@NonNull ViewModelStore store, @NonNull Factory factory) { mFactory = factory; mViewModelStore = store; } }
通过 ViewModelProvider
获取 model 实例时,使用的是他的 get
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class ViewModelProvider { private static final String DEFAULT_KEY = "android.arch.lifecycle.ViewModelProvider.DefaultKey"; @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); // 当使用不同的类加载器加载同一个类的时候,这里会是 false 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; } }
ViewModelProvider
他的职责就是从 ViewModelStore
里取出对象,如果对象不存在,就新创建一个,并把新创建的这个对象放到 ViewModelStore
。
ViewModelStore 和 ViewModelProvider
一样,ViewModelStore
也有一个工厂类叫 ViewModelStores
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class ViewModelStores { @NonNull @MainThread public static ViewModelStore of (@NonNull FragmentActivity activity) { if (activity instanceof ViewModelStoreOwner) { return ((ViewModelStoreOwner) activity).getViewModelStore(); } return holderFragmentFor(activity).getViewModelStore(); } } public interface ViewModelStoreOwner { @NonNull ViewModelStore getViewModelStore () ; }
HolderFragment
实现了 ViewModelStoreOwner
接口,holderFragmentFor(activity)
返回 activity
对应的 holderFragment
后,即可以拿到 ViewModelStore
实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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); } public final void clear () { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } }
HolderFragment HolderFragment
是整个实现的核心。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 public class HolderFragment extends Fragment implements ViewModelStoreOwner { public HolderFragment () { setRetainInstance(true ); } @Override public void onCreate (@Nullable Bundle savedInstanceState) { super .onCreate(savedInstanceState); sHolderFragmentManager.holderFragmentCreated(this ); } public static HolderFragment holderFragmentFor (FragmentActivity activity) { return sHolderFragmentManager.holderFragmentFor(activity); } static class HolderFragmentManager { private Map<Activity, HolderFragment> mNotCommittedActivityHolders = new HashMap<>(); private ActivityLifecycleCallbacks mActivityCallbacks = new EmptyActivityLifecycleCallbacks() { @Override public void onActivityDestroyed (Activity activity) { HolderFragment fragment = mNotCommittedActivityHolders.remove(activity); if (fragment != null ) { Log.e(LOG_TAG, "Failed to save a ViewModel for " + activity); } } }; private boolean mActivityCallbacksIsAdded = false ; HolderFragment holderFragmentFor (FragmentActivity activity) { FragmentManager fm = activity.getSupportFragmentManager(); HolderFragment holder = findHolderFragment(fm); if (holder != null ) { return holder; } holder = mNotCommittedActivityHolders.get(activity); if (holder != null ) { return holder; } if (!mActivityCallbacksIsAdded) { mActivityCallbacksIsAdded = true ; activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks); } holder = createHolderFragment(fm); mNotCommittedActivityHolders.put(activity, holder); return holder; } private static HolderFragment createHolderFragment (FragmentManager fragmentManager) { HolderFragment holder = new HolderFragment(); fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss(); return holder; } } }
HolderFragment
对 ViewModelStoreOwner
实现是相当直接的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class HolderFragment extends Fragment implements ViewModelStoreOwner { private ViewModelStore mViewModelStore = new ViewModelStore(); @Override public void onDestroy () { super .onDestroy(); mViewModelStore.clear(); } @NonNull @Override public ViewModelStore getViewModelStore () { return mViewModelStore; } }
到这里,ViewModel
的实现我们就看完了。需要注意的是,ViewModel
还支持 fragment
,这部分跟 activity
是类似的,有兴趣的读者自己看一看就好。
---
> @大熊:ViewModelStores.of(FragmentActivity)需要区分下Support Library的版本,如果在v27.1.0版本及以上的,FragmentActivity已经实现了ViewModelStoreOwner接口,最终是通过FragmentActivity.onRetainNonConfigurationInstance()完成ViewModelStore的存储的,v27.1.0版本以下才是通过Fragment.setRetainInstance(true)实现。