Android Jetpack——ViewModel源码解析

一、前言

之前我们已经介绍了ViewModel的意义和使用方式。我们知道,在一个Activity创建ViewModel对象的时候,当由于系统配置变化导致Activity销毁重建的时候,ViewModel对象并不会被有任何影响,由此可知在ViewModel中存储的数据,也不会发生变化。这对于我们开发者来说是很方便的。
我们知道Activity的onSaveInstanceState和onRestoreInstanceState也可以做到这一点,但是我们知道onSaveInstanceState和onRestoreInstanceState是通过把数据序列化到内存,再从内存中反序列化出来。通常是针对一些可以序列化和反序列化的小量数据,如果是大量的数据,或者没有序列化的,则不行了。
了解了ViewModel的强大的功能之后,我们先用一张图来描述ViewModel的生命周期的变化:


image.png

从图中我们可以看到,只有Activity真正的销毁的时候,ViewModel才会被清除掉,对应图中的onCleared方法。

二、源码解析

下面我们来分析ViewModel的源码。我们先看下ViewModel对象的创建方式:

   viewModel = ViewModelProviders.of(this).get(MainViewModel.class);

代码很简单,首先调用ViewModelProviders的of方法创建ViewModelProvider对象。其实从类的命名上看就很容易理解,ViewModelProviders和ViewModelProvider只差一个s,ViewModelProviders是一个集合,ViewModelProvider是集合中的一个对象,of(this)则是通过传入当前Activitiy的实例作为key,获取ViewModelProviders中ViewModelProvider对象。是不是这个意思呢?我们继续分析:

 @NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull Fragment fragment) {
        return of(fragment, null);
    }

  @NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }

   @NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {
        Application application = checkApplication(checkActivity(fragment));
        if (factory == null) {
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        return new ViewModelProvider(ViewModelStores.of(fragment), factory);
    }

  @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);
    }

我们看到of方法中有四个重载的方法,她们的区别就是传入的this是Activity还是Fragment,还有就是,是否有Factory 对象。如果没有Factory对象,则创建默认的Factory。然后通过以下方式返回ViewModelProvider 对象

 return new ViewModelProvider(ViewModelStores.of(fragment), factory);

我们看下ViewModelProvider的构造函数:

  public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        mFactory = factory;
        this.mViewModelStore = store;
    }

ViewModelStore 和Factory 对象顾名思义ViewModelStore 是用来存储ViewModel的Factory 是用来创建ViewModel的。通过ViewModelStores.of(fragment)创建获取ViewModelStore实例,接着我们看下ViewModelStores.of(fragment)的实现

  @NonNull
    @MainThread
    public static ViewModelStore of(@NonNull Fragment fragment) {
        if (fragment instanceof ViewModelStoreOwner) {
            return ((ViewModelStoreOwner) fragment).getViewModelStore();
        }
        return holderFragmentFor(fragment).getViewModelStore();
    }

    /**
     * @hide
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    public static HolderFragment holderFragmentFor(Fragment fragment) {
        return sHolderFragmentManager.holderFragmentFor(fragment);
    }

 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 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;
        }

我们看到获取ViewModelStore实例最终调用了holderFragmentFor方法获取HolderFragment 实例holder ,而HolderFragment 继承了ViewModelStoreOwner。在holderFragmentFor方法中首先根据activity作为key,判断holder 是否存在。如果存在里,就直接返回holder。

  HolderFragment holder = findHolderFragment(fm);
            if (holder != null) {
                return holder;
            }
            holder = mNotCommittedActivityHolders.get(activity);
            if (holder != null) {
                return holder;
            }

如果不存在则创建新的holder返回,并把holde存到mNotCommittedActivityHolders这个Map中,以Activity作为key。

 if (!mActivityCallbacksIsAdded) {
                mActivityCallbacksIsAdded = true;
                activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
            }
            holder = createHolderFragment(fm);
            mNotCommittedActivityHolders.put(activity, holder);
            return holder;

这样一来我们可以知道,只要HolderFragment 没有被销毁,mNotCommittedActivityHolders这个Map就会存在,那么存放在Map中的ViewModelStoreOwner holder就存在。

return holderFragmentFor(fragment).getViewModelStore();

然后通过getViewModelStore()方法可以得到ViewModelStore对象。
接着我们看下get方法

  viewModel = ViewModelProviders.of(this).get(MainViewModel.class);

    @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;
    }

我们很容易知道,首先从Map中根据key获取ViewModel 对象

ViewModel viewModel = mViewModelStore.get(key);

如果viewModel 不为空,则返回,否则创建一个ViewModel对象,存放在Map中。

  ViewModel oldViewModel = mMap.put(key, viewModel);

并且我们知道存放ViewModel的Key和Activity或者Fragment是对应起来的。所以说当Activity重建的时候,只要mViewModelStore对象还是原来的对象,那么ViewModel对象就不会变,而且我们在上面分析知道mViewModelStore又存放到了HolderFragment中,也是存放到了Map中,所以只要HolderFragment没有被销毁,mViewModelStore就不会被销毁。mViewModelStore没有被销毁,ViewModel就没有被销毁。ViewModel没有被销毁,ViewModel里面的数据就没有被销毁。因此得出了我们的结论。在Activity销毁重建的时候,ViewModel里的数据是不会丢失的。

三、小结

我们对ViewModel的源码做一个小结:
1、创建HolderFragment,并在HolderFragment中初始化Map<Activity, HolderFragment> mNotCommittedActivityHolders 用于存放 HolderFragment holder。
2、从HolderFragment 获取ViewModelStore mViewModelStore
3、ViewModelStore 用于存放ViewModel对象,创建ViewModelProvider实例,传入ViewModelStore 对象,对ViewModelProvider中的ViewModelStore进行初始化。
4、通过 mViewModelStore.put(key, viewModel);获取ViewModel实例。
其实ViewModel最核心的部分就是HolderFragment 中存放了ViewModelStore 。因为Activity在销毁重建的时候HolderFragment 并不收到影响,所以ViewModelStore 不会丢失。从而下面的一系列得到ViewModel对象不会销毁。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容