美文网首页
Jetpack-ViewModel源码分析

Jetpack-ViewModel源码分析

作者: 积木小玩家 | 来源:发表于2019-01-19 15:17 被阅读0次

    ViewModel简介

    1. Activity或Fragment有自己的生命周期被Framework所管理,Framework可能会根据用户的一些操作以及设备的状态对Actvity或Fragment进行销毁和重建。伴随着Activity或Fragment的销毁和重建,它们当中的数据也会随着一起销毁和重建。对于一些简单的数据,Activity可以使用onSaveInstanceState()方法,并从onCreate的bundle中重新获取,但这一方法仅仅适合一些简单的UI状态,对于列表型这种庞大的数据类型并不适合。
    2. Activity或Fragment经常会做一些异步的耗时操作,需要管理这些异步操作得到的数据,并在destroyed的时候清理它们,从而避免内存溢出这类问题的发生。管理数据的成本较大,另外configurationChanged发生时,部分资源和数据需要重新请求,降低了性能。
    3. Activity或Fragment本身需要处理很多用户的输入事件并和操作系统相关操作们,如果还维护管理业务数据和资源,会导致Activity和Fragment过于庞大。

    特点

    以关联生命周期的方式来存储和管理UI相关的数据,即使configuration发生改变(比如旋转屏幕,系统语言字体变化),数据仍然可以存在不会销毁。
    Activity和Fragment之间,多个Fragment之间共享数据,轻松解决Activity和Fragment之间数据通信提高复杂性问题。

    职责

    ViewModel类图

    ViewModel
    ViewModel 对象为特定的界面组件提供数据,并包含数据处理业务逻辑,以与模型进行通信。
    ViewModel被更换或者清除时,通过onCleard释放持有资源。

    ViewModelStore
    负责缓存ViewModel,通过clear释放ViewModel持有资源。

    ViewModelStoreOwner
    负责持有ViewModelStore,Support Library 28中Fragemnt,Activity和HoldFragment是ViewModelStoreOwner的具体实现类,他们内部持有ViewModelStore。

    ViewModelStores
    负责通过Activity或者Fragment获取ViewModelStore。
    1. 如果Activity或者Fragment已实现ViewModelStoreOwner接口,直接返回内部ViewModelStore;
    2. 如果Activity或者Fragment未实现ViewModelStoreOwner接口,通过HoldFragment机制获得ViewModelStore;

    ViewModelProvider
    负责获取ViewModel实例,构造ViewModelProvider需要ViewModelStore和Factory。

    1. 根据ViewModel Class名称,从ViewModelStore缓存中获取ViewModel实例;
    2. 步骤1获取成功,直接返回实例;
    3. 步骤1获取失败,通过Factory反射构造ViewModel,内置Factory有NewInstanceFactory,AndroidViewModelFactory。
    4. 使用ViewModelStore缓存步骤3创建的ViewModel实例后,返回ViewModel实例。

    ViewModelProviders
    负责为Activity和Fragment创建ViewModelProvider。

    源码解析

    使用

    在Activity或者Fragment中获得ViewModel实例。

    class MainFragment : Fragment() {
        companion object {
            fun newInstance() = MainFragment()
        }
        private lateinit var viewModel: MainViewModel
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View {
            return inflater.inflate(R.layout.main_fragment, container, false)
        }
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
    
            viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        }
    }
    

    上面的样例代码中使用最简单的方式构造ViewModel,通过ViewModelProvider内部自动构造ViewModel,如果需要把Repository等其他对象内置到ViewModel中,可以自定义Factory去实现。这篇文章主要是分析ViewModel内部实现机制,不对ViewModel的构造太多介绍,可以参见android-architecture-components-BasicSample

    关键源码分析

    相关源码中比较关键是的ViewModelStores,HoldFragment。

    ViewModelStores

    public class ViewModelStores {
        private ViewModelStores() {
        }
        public static ViewModelStore of(@NonNull FragmentActivity activity) {
            if (activity instanceof ViewModelStoreOwner) {
                return ((ViewModelStoreOwner) activity).getViewModelStore();
            }
            return holderFragmentFor(activity).getViewModelStore();
        }
        public static ViewModelStore of(@NonNull Fragment fragment) {
            if (fragment instanceof ViewModelStoreOwner) {
                return ((ViewModelStoreOwner) fragment).getViewModelStore();
            }
            return holderFragmentFor(fragment).getViewModelStore();
        }
    }
    
    1. 如果Activity或者Fragment实现ViewModelOwner,直接返回内部的ViewModelStore;
    2. 否则,通过HoldFragment获得ViewModelStore。

    注意:无论哪种方式,都实现了对应Activity或者Fragment只存在一个ViewModelStore,且根据Activity和Fragment生命周期销毁(configurationChanged除外)。

    HoldFragment

    public class HolderFragment extends Fragment implements ViewModelStoreOwner {
        //仅存在一个HolderFragmentManager实例
        private static final HolderFragmentManager sHolderFragmentManager = new HolderFragmentManager();
        private ViewModelStore mViewModelStore = new ViewModelStore();
        public HolderFragment() {
    //保留Fragment
            setRetainInstance(true);
        }
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            sHolderFragmentManager.holderFragmentCreated(this);
        }
        @Override
        public void onDestroy() {
            super.onDestroy();
            mViewModelStore.clear();
        }
        @Override
        public ViewModelStore getViewModelStore() {
            return mViewModelStore;
        }
        public static HolderFragment holderFragmentFor(FragmentActivity activity) {
            return sHolderFragmentManager.holderFragmentFor(activity);
        }
        
    static class HolderFragmentManager {
            private Map<Activity, HolderFragment> mNotCommittedActivityHolders = new HashMap<>(); 
    private Map<Fragment, HolderFragment> mNotCommittedFragmentHolders = new HashMap<>();
    ...
    }
    

    1. HoldFragment实现ViewModelStoreOwner接口;
    2.setRetainInstance,configurationChanged后,短暂保留Fragment,从而保留ViewModelStore[参考];
    3. onDestory时,ViewModelStore clear;
    4. sHolderFragmentManager仅存在一个实例;
    5. NotCommitted变量和holderFragmentCreated规避为一个Activity或者Fragment创建多个HoldFragment。

    Support Library

    support v4 28.0.0 中FragmentActivity和Fragment已实现ViewModelStoreOwner接口,不再需要HoldFragment机制支持ViewModel特性。

    Fragment

    通过在OnDestroy方法对configuration的判断,保留下ViewModelStore。

    public class Fragment implements LifecycleOwner, ViewModelStoreOwner {
        ViewModelStore mViewModelStore;
        public ViewModelStore getViewModelStore() {
            if (this.getContext() == null) {
                throw new IllegalStateException("Can't access ViewModels from detached fragment");
            } else {
                if (this.mViewModelStore == null) {
                    this.mViewModelStore = new ViewModelStore();
                }
                return this.mViewModelStore;
            }
        }
        public void onDestroy() {
            this.mCalled = true;
            FragmentActivity activity = this.getActivity();
            boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations();
            if (this.mViewModelStore != null && !isChangingConfigurations) {
                this.mViewModelStore.clear();
            }
        }
    }
    

    FragmentActivity

    了解下NonConfigurationInstances,此处不再赘述。

    public class FragmentActivity extends SupportActivity implements ViewModelStoreOwner {
        private ViewModelStore mViewModelStore;
        public ViewModelStore getViewModelStore() {
            if (this.getApplication() == null) {
                throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
            } else {
                if (this.mViewModelStore == null) {
                    FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
                    if (nc != null) {
                        this.mViewModelStore = nc.viewModelStore;
                    }
    
                    if (this.mViewModelStore == null) {
                        this.mViewModelStore = new ViewModelStore();
                    }
                }
                return this.mViewModelStore;
            }
        }
       protected void onCreate(@Nullable Bundle savedInstanceState) {
            this.mFragments.attachHost((Fragment)null);
            super.onCreate(savedInstanceState);
            FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
            if (nc != null && nc.viewModelStore != null && this.mViewModelStore == null) {
                this.mViewModelStore = nc.viewModelStore;
            }
       }
        protected void onDestroy() {
            super.onDestroy();
            if (this.mViewModelStore != null && !this.isChangingConfigurations()) {
                this.mViewModelStore.clear();
            }
            this.mFragments.dispatchDestroy();
        }
    }
    

    总结

    Jetpack中ViewModel的设计和实现并不是很复杂,ViewModel是Google官方推荐MVVM模式实现的重要组成部分,ViewModel与Lifecycle和LiveData等Jetpack组件组合使用会更加发挥其作用,待后续深入分析其他Jetpack组件源码实现。

    相关文章

      网友评论

          本文标题:Jetpack-ViewModel源码分析

          本文链接:https://www.haomeiwen.com/subject/foczdqtx.html