本篇主要关注 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)实现。