这是Android官方架构组件系列的第三篇文章,前两篇点击标题即可跳转
Android 官方架构组件(一)——Lifecycle
Android官方架构组件(二)——LiveData

ViewModel类主要用来存储和管理与UI相关的数据,它能够让数据在屏幕旋转等配置信息改变导致UI重建的情况下不被销毁。

ViewModel生命周期

ViewModel 对象存活在系统中不被回收的时间是由创建ViewModel传递给ViewModelProvider的Lifecycle决定的。ViewModel将一直留在内存中,直到限定其存在时间范围的Lifecycle生命周期结束。对于Activity,是在Activity destroy时;而对于Fragment,是在Fragment detach时。

下图说明了Activity经历屏幕旋转直到最终destroyed掉这整个过程中所经历的各个生命周期。该图还在关联的Activity生命周期的旁边显示了ViewModel的生命周期。

我们可以看出,ViewModel的生命周期贯穿Activity始终,直到Activity正常结束,并不会因为屏幕旋转等系统原因而导致ViewModel生命周期提前结束。同理Fragment对于ViewModel也一样。

本文,我们不讨论ViewModel的使用,而是直接分析它的原理。

ViewModel原理分析

我们分析源码的时候要带着明确目的带着问题去分析,从小见大,一个一个小问题解决,无头苍蝇似的扑进源码中,可能事倍功半。

在分析ViewModel源码之前,我们先介绍一下ViewModel组件中重要的几个类:

  • ViewModel、ViewModelProvider、HolderFragment、ViewModelStore

    上面的类图简单地描述出了这几个类的作用以及关系,算是一个小概括,下面,我们直接进入源码分析它们具体的实现,以及它们是如何联系起来的。

(在这里默认大家已经知道了ViewModel的使用)我们知道ViewModel实例的创建是通过 ViewModelProviders.of(this).get(XxxViewModel.class)生成的,这行代码可以分为两个步骤:

  • 第一步:通过ViewModelProviders.of(this)生成ViewModelProvider对象;
  • 第二步:通过viewModelProvider.get(XxxViewModel.class)生成相对ViewModel对象。
    下面我们的源码就针对这两个步骤分析一下ViewModel架构中重要的几个类。

ViewModelProvider

ViewModelProvider 是通过 ViewModelProviders.of(this)生成的,我们进入源码看看:

    public static ViewModelProvider of(@NonNull FragmentActivity activity) {        return of(activity, null);    }        public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) {        Application application = checkApplication(activity);        if (factory == null) {            // 上面的类图,我们已经说了,生成 ViewModelProvider 实例的时候,如果 factory 传 null,            // 系统会默认使用 AndroidViewModelFactory 作为 ViewModel 的生产类            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);        }            // 实例化创建一个 ViewModelProvider 对象返回        return new ViewModelProvider(ViewModelStores.of(activity), factory);    }

可以看到,ViewModelProviders.of()最终会new一个ViewModelProvider对象返回。在创建ViewModelProvider的时候,需要传入两个参数,ViewModelStore以及Factory。在这里,我们先不讨论ViewModelStores.of(activity)是如何实例化返回ViewModelStore对象的,在后面,我们会说到。

先来看一下Factory类,它的定义很简单:

    public interface Factory {        // 只有一个 create 方法需要重写,这个方法就返回 ViewModel 对象,        // 我们可以选择默认使用 AndroidViewModelFactory,也可以自定义 Factory        <T extends ViewModel> T create(@NonNull Class<T> modelClass);    }

当我们传入的factory参数为null的时候,会默认使用AndroidViewModelFactory:

    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;        }            private Application mApplication;            public AndroidViewModelFactory(@NonNull Application application) {            mApplication = application;        }            @NonNull        @Override        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {                // 当 modelClass 类继承自 AndroidViewModel            if (AndroidViewModel.class.isAssignableFrom(modelClass)) {                //noinspection TryWithIdenticalCatches                try {                    // 调用 modelClass 类中带有 Application 参数的构造方法创建一个 ViewMode 返回                    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);                }            }                // 如果 modelClass 类不是继承自 AndroidViewModel,调用 AndroidViewModelFactory 的            // 父类 NewInstanceFactory 的 create 方法生成 ViewModel 对象返回            return super.create(modelClass);        }    }

AndroidViewModelFactory的父类NewInstanceFactory也是非常简单:

    public static class NewInstanceFactory implements Factory {            @SuppressWarnings("ClassNewInstance")        @NonNull        @Override        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {            //noinspection TryWithIdenticalCatches            try {                // 直接通过反射调用 modelClass 类的无参构造函数实例化一个 ViewModel 对象返回                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的分析,在传入的factory参数为null的前提下,我们可以得出以下结论:

  • 如果我们自定义的model继承自ViewModel,需要有一个默认无参的构造方法;
  • 如果我们自定义的model继承自AndroidViewModel,必须要有一个以Application为唯一参数的构造函数。

当然我们也可以自定义Factory,在这里就不讨论了,广大聪明的读者才是最法力无边的~

ViewModelStore

上面我们知道了在构造ViewModelProvider的时候,会通过ViewModelStores.of()方法获取到一个ViewModelStore对象。ViewModelStores类是用于提供返回ViewModelStore对象的,下面我们来看看ViewModelStores.of()究竟做了什么?

    public class ViewModelStores {            private ViewModelStores() {        }            @NonNull        @MainThread        public static ViewModelStore of(@NonNull FragmentActivity activity) {                // 开发者可以选择自己让 Activity 继承 ViewModelStoreOwner,然后实现 getViewModelStore 方法            if (activity instanceof ViewModelStoreOwner) {                return ((ViewModelStoreOwner) activity).getViewModelStore();            }                // holderFragmentFor(activity)方法返回继承了 ViewModelStoreOwner 的 HolderFragment 实例,            // 调用这个 HolderFragment 对象的 getViewModelStore() 即可以拿到 ViewModelStore 实例。            return holderFragmentFor(activity).getViewModelStore();        }            @NonNull        @MainThread        public static ViewModelStore of(@NonNull Fragment fragment) {            // 同理,fragment 也可以继承 ViewModelStoreOwner ,实现 getViewModelStore 方法            if (fragment instanceof ViewModelStoreOwner) {                return ((ViewModelStoreOwner) fragment).getViewModelStore();            }            // 同上            return holderFragmentFor(fragment).getViewModelStore();        }    }

可以看出,ViewModelStores.of()方法主要就是从ViewModelStoreOwner对象中获取ViewModelStore对象。至于holderFragmentFor()方法究竟做了什么?我们下面在继续分析,现在,先看看ViewModelStore:

    public class ViewModelStore {            // 用 HashMap 存储 ViewModel 对象        private final HashMap<String, ViewModel> mMap = new HashMap<>();            // 新添 ViewModel        final void put(String key, ViewModel viewModel) {            // 如果对应 key 的 ViewModel 已经存在,那么覆盖它,并且调用它的 onCleared 方法            ViewModel oldViewModel = mMap.put(key, viewModel);            if (oldViewModel != null) {                oldViewModel.onCleared();            }        }            // 获取指定 key 的 ViewModel        final ViewModel get(String key) {            return mMap.get(key);        }            // 调用所有 ViewModel 的 onCleared 方法,并且清空整个 HashMap        public final void clear() {            for (ViewModel vm : mMap.values()) {                vm.onCleared();            }            mMap.clear();        }    }

ViewModelStore的实现很简单,主要的作用就是对ViewModel进行存储管理,通过一个HashMap保存了所有的ViewModel,分别通过put方法以及get方法添加和获取ViewModel,通过clear方法遍历调用所有ViewModel的onCleared方法并且清空map。

接下来,我们来看看最核心的一个类,HolderFragment。

HolderFragment

前面我们分析ViewModelStores.of()方法的时候,提到过调用静态方法holderFragmentFor()方法能够返回一个继承了ViewModelStoreOwner的HolderFragment实例,现在我们就来看看HolderFragment这个类究竟是何方神圣?为什么当Activity由于屏幕旋转等被系统销毁时,这个Fragment实例也不会被销毁?

    public class HolderFragment extends Fragment implements ViewModelStoreOwner {        private static final String LOG_TAG = "ViewModelStores";            // 这是什么?请看下面注释分析        private static final HolderFragmentManager sHolderFragmentManager = new HolderFragmentManager();            @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)        public static final String HOLDER_TAG = "android.arch.lifecycle.state.StateProviderHolderFragment";            // 这就是我们存放 ViewModel 的 ViewModelStore,就定义在 HolderFragment里        private ViewModelStore mViewModelStore = new ViewModelStore();            public HolderFragment() {            // 划重点啦!!!为什么当 activity 由于屏幕旋转等被系统销毁时,            // 这个 fragment 实例也不会被销毁?因为设置了 setRetainInstance(true)            setRetainInstance(true);        }            @Override        public void onCreate(@Nullable Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            // 当 Fragment 的 onCreate 方法执行,说明了 Fragment 已经成功添加到了 Activity,            // sHolderFragmentManager 是 HolderFragmentManager类,它的 holderFragmentCreated()方法            // 是将该 Fragment 从 mNotCommittedActivityHolders 或 mNotCommittedFragmentHolders 中移除            // (HolderFragmentManager 的说明,请看下面的注释)            sHolderFragmentManager.holderFragmentCreated(this);        }            @Override        public void onSaveInstanceState(Bundle outState) {            super.onSaveInstanceState(outState);        }            @Override        public void onDestroy() {            super.onDestroy();            // 当一个设置了 setRetainInstance(true) 的 Fragment 的 onDestroy 方法被调用,            // 证明它依附的 Activity 已经寿终正寝,所以调用 mViewModelStore.clear(),            // 前面我们已经说了,这个 clear 方法会调用所有 ViewModel 对象的 onCleared 方法            // 并且清空它们,我们可以在 ViewModel 的onCleared 方法做一些处理,以免起来不必要的            // 内存泄漏等问题            mViewModelStore.clear();        }            // 该方法用于给外部调用,返回 ViewModelStore        @Override        public ViewModelStore getViewModelStore() {            return mViewModelStore;        }            // 静态方法,没 ViewModelStores.of 方法中被调用        // 作用:在 activity 中添加一个 HolderFragment 用于存储存放了ViewModel对象的ViewModelStore        public static HolderFragment holderFragmentFor(FragmentActivity activity) {            return sHolderFragmentManager.holderFragmentFor(activity);        }            // 静态方法,没 ViewModelStores.of 方法中被调用        // 作用:在 fragment 中添加一个 HolderFragment 用于存储存放了ViewModel对象的ViewModelStore        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)        public static HolderFragment holderFragmentFor(Fragment fragment) {            return sHolderFragmentManager.holderFragmentFor(fragment);        }            // 上面的大部分操作都是基于HolderFragmentManager,我们来分析下这个类        @SuppressWarnings("WeakerAccess")        static class HolderFragmentManager {                // 存放还没被系统正式添加到 Activity 中的 HolderFragment            private Map<Activity, HolderFragment> mNotCommittedActivityHolders = new HashMap<>();            private Map<Fragment, HolderFragment> mNotCommittedFragmentHolders = new HashMap<>();                // 声明定义了一个能够感知 Activity 生命周期的 ActivityLifecycleCallbacks             private ActivityLifecycleCallbacks mActivityCallbacks =                    new EmptyActivityLifecycleCallbacks() {                        @Override                        public void onActivityDestroyed(Activity activity) {                            // 当 Activity destroy 的时候,清除 mNotCommittedActivityHolders 中保存                            // 的对应 HolderFragment。前面我们分析了 HolderFragment 的 onCreate 方法中                            // 会请一次 mNotCommittedActivityHolders,为什么在这么还要多此一举呢?其实                            // 并不是多此一举,因为 Fragment 有可能还没创建完,Activity 就夭折了,那这样子                            // HodlerFragment 的 onCreate 就无法调用,所以在加多一层清理机制,确保能够                            // 清除掉(不得不感叹,谷歌官方的严谨以及对源码的掌控理解能力)                            HolderFragment fragment = mNotCommittedActivityHolders.remove(activity);                            if (fragment != null) {                                Log.e(LOG_TAG, "Failed to save a ViewModel for " + activity);                            }                        }                    };                private boolean mActivityCallbacksIsAdded = false;                private FragmentLifecycleCallbacks mParentDestroyedCallback =                    new FragmentLifecycleCallbacks() {                        @Override                        public void onFragmentDestroyed(FragmentManager fm, Fragment parentFragment) {                            // 与 mActivityCallbacks 的分析同理                            super.onFragmentDestroyed(fm, parentFragment);                            HolderFragment fragment = mNotCommittedFragmentHolders.remove(                                    parentFragment);                            if (fragment != null) {                                Log.e(LOG_TAG, "Failed to save a ViewModel for " + parentFragment);                            }                        }                    };                // HolderFragment 的 onCreate 生命周期被回调,就会调用这个方法,清除            // mNotCommittedActivityHolders 或者 mNotCommittedFragmentHolders 中            // 的引用的 HolderFragment            void holderFragmentCreated(Fragment holderFragment) {                Fragment parentFragment = holderFragment.getParentFragment();                if (parentFragment != null) {                    mNotCommittedFragmentHolders.remove(parentFragment);                    parentFragment.getFragmentManager().unregisterFragmentLifecycleCallbacks(                            mParentDestroyedCallback);                } else {                    mNotCommittedActivityHolders.remove(holderFragment.getActivity());                }            }                private static HolderFragment findHolderFragment(FragmentManager manager) {                if (manager.isDestroyed()) {                    throw new IllegalStateException("Can't access ViewModels from onDestroy");                }                    Fragment fragmentByTag = manager.findFragmentByTag(HOLDER_TAG);                if (fragmentByTag != null && !(fragmentByTag instanceof HolderFragment)) {                    throw new IllegalStateException("Unexpected "                            + "fragment instance was returned by HOLDER_TAG");                }                return (HolderFragment) fragmentByTag;            }                private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {                HolderFragment holder = new HolderFragment();                fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();                return holder;            }                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);                // 我们新添加 add 的 Fragment 并不会马上就执行添加完(也就是说,这个方法执行完成后,马上再                // 调用一次,上面的 findHolderFragment 会返回 null。但是这没有关系,因为接下来我们还可                // 从 mNotCommittedActivityHolders 获取到对应的实例),所以我们这里先把他放在                // mNotCommittedActivityHolders 中。Not Committed 表示 fragment 的 commit 还没有完成                mNotCommittedActivityHolders.put(activity, holder);                return holder;            }                HolderFragment holderFragmentFor(Fragment parentFragment) {                FragmentManager fm = parentFragment.getChildFragmentManager();                HolderFragment holder = findHolderFragment(fm);                if (holder != null) {                    return holder;                }                holder = mNotCommittedFragmentHolders.get(parentFragment);                if (holder != null) {                    return holder;                }                    parentFragment.getFragmentManager().registerFragmentLifecycleCallbacks(mParentDestroyedCallback, false);                holder = createHolderFragment(fm);                // 同上                mNotCommittedFragmentHolders.put(parentFragment, holder);                return holder;            }        }    }

通过上面的注释,我们已经详细地对HolderFragment这个核心类做了分析,总结一下:

  • HolderFragment通过设置setRetainInstance(true),使得自身能够不受到屏幕旋转等configuration
    changes影响而存活,直到依附的Activity正常结束。
  • 因为HolderFragment的生命周期,ViewModelStore对象保存在HolderFragment中,而ViewModel又存储在ViewModelStore中,这就是为什么我们说ViewModel类能够让数据在屏幕旋转等配置信息改变导致UI重建的情况下不被销毁。

总结

ViewModel的分析就到此为止了,我们主要解决了两个问题:

  • ViewModel是怎样创建的?通过调用ViewModelProviders.of(this).get(XxxViewModel.class)或者ViewModelProviders.of(this,
    mFactory).get(XxxViewModel.class)返回ViewModel。最终ViewModel实际上是由Factory创建,当我们不传Factory参数时,系统默认使用AndroidViewModelFactory作为Factory,通过反射生成ViewModel实例对象返回。
  • ViewModel以及存储在其中的数据是怎样在屏幕旋转下依然保留在内存中的?
    GC垃圾回收机制不会回收被强引用的对象。在开发过程中,我们需要存储的数据被ViewModel引用,ViewModel被ViewModelStore引用,而ViewModelStore又被HolderFragment引用,于是就形成了一条引用链:HolderFragment->ViewModelStore->ViewModel->我们想要存储的数据(最佳实践是LiveData)。通过上面HolderFragment的分析,我们知道HodlerFragment在创建时,设置了setRetainInstance(true),因此它使得自身能够不受到屏幕旋转等configuration
    changes影响而存活,直到依附的Activity正常结束。

最后,附上一副时序图供诸位朋友们帮助理解记忆:

更多相关文章

  1. Android集成Huawei PUSH(四)——客户端开发
  2. Android中定时器Timer和TimerTask的启动,停止,暂停,继续等操作实例
  3. android中跨进程通讯的4种方式
  4. Android(安卓)解析gbk、gb2312编码的xml文件(转)
  5. Android通过JNI调用驱动程序(完全解析实例)
  6. Flutter通过BasicMessageChannel实现Flutter 与Android(安卓)iOS
  7. android 提升性能总结
  8. android 生命周期复习1
  9. android实用测试方法之Monkey与MonkeyRunner

随机推荐

  1. Android(安卓)底部弹出Activity
  2. Android(安卓)在部分华为手机上出现乱码
  3. android 8.1Settings添加设置项
  4. android项目集成 flutter
  5. 解决android http请求带中文参数会乱码(u
  6. Android(安卓)修改actionbar标题的颜色和
  7. Android开源代码汇总
  8. Android中常用adb命令及Log使用
  9. textView写点击选中和没选中效果
  10. mac下android studio安装plantuml插件