ViewModel源码解析

作者: 雯艺雪 | 来源:发表于2019-08-16 17:37 被阅读0次

    0.前言

    viewModel是什么?
    官方解释:

    The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.
    ViewModel类旨在以生命周期有意识的方式存储和管理ui相关的数据。ViewModel类允许数据在配置更改(如屏幕旋转)之后存活。

    这里明确指出,ViewModel可以感知activity生命周期,并在配置更改后允许数据存活(原理是内部类HolderFragment调用了setRetainInstance(true),从而当屏幕旋转时,activity重绘但Fragment不重绘),与viewModel绑定的Activity必须继承于FragmentActivity。
    官方网址
    以及关于ViewModel与Activity生命周期的关联图:

    viewmodel-lifecycle.png

    1.使用

    ViewModel一般与LiveData结合使用:
    添加依赖

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:1.1.1"
    // alternatively, just ViewModel
    implementation "android.arch.lifecycle:viewmodel:1.1.1"
    // alternatively, just LiveData
    implementation "android.arch.lifecycle:livedata:1.1.1"

    package foolish
    
    import android.arch.lifecycle.LifecycleOwner
    import android.arch.lifecycle.MutableLiveData
    import android.arch.lifecycle.Observer
    import android.arch.lifecycle.ViewModel
    import beans.response.TaskBean
    import com.uber.autodispose.AutoDispose
    import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
    import comment.LogUit
    import io.reactivex.Observable
    import io.reactivex.android.schedulers.AndroidSchedulers
    import io.reactivex.observers.DisposableObserver
    import io.reactivex.schedulers.Schedulers
    
    
    class TestModel:ViewModel(){
        val taskLiveData= MutableLiveData<Observable<TaskBean>>()//ViewModel内部持有LiveData
        fun initData( lifecycleOwner: LifecycleOwner){
            //此处选择在TestModel内部处理LiveData(网上教程很多是把LiveData放在View中处理)
            taskLiveData.observe(lifecycleOwner,object : Observer<Observable<TaskBean>>{
                override fun onChanged(observable: Observable<TaskBean>?) {
                    observable!!.subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .`as`(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner)))//使用AutoDispose绑定lifecycleOwner,自动取消订阅
                            .subscribe(object : DisposableObserver<TaskBean>() {
                                override fun onComplete() {
    
                                }
    
                                override fun onNext(t: TaskBean) {
                                    LogUit.printI("TaskPresentPrint", "t=${t.toString()}")
                                }
    
                                override fun onError(e: Throwable) {
                                    //处理网略错误
                                }
    
                            })
                }
    
            })
        }
    
    
    }
    

    Activity中调用:

     private val registerOrLoginModel by lazy { ViewModelProviders.of(this).get(TestModel::class.java) }
    

    2.源码分析

    先来看看of做了什么

    @NonNull
        @MainThread
        public static ViewModelProvider of(@NonNull FragmentActivity activity) {
            //如果没有传递factory过来,默认null
            return of(activity, null);
        }
    
     @NonNull
        @MainThread
        public static ViewModelProvider of(@NonNull FragmentActivity activity,
                @Nullable Factory factory) {
            Application application = checkApplication(activity);
            //如果没有传递factory过来,就自己新建一个
            if (factory == null) {
                factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
            }
            //从ViewModelStores里面取出对应Activity的ViewModelProvider
            return new ViewModelProvider(ViewModelStores.of(activity), factory);
        }
    

    在查看ViewModelProvider源码之前,先来看看ViewModelStores:

    • ViewModelStores
    /*
     * Copyright (C) 2017 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package android.arch.lifecycle;
    
    import static android.arch.lifecycle.HolderFragment.holderFragmentFor;
    
    import android.support.annotation.MainThread;
    import android.support.annotation.NonNull;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    
    /**
     * Factory methods for {@link ViewModelStore} class.
     */
    @SuppressWarnings("WeakerAccess")
    public class ViewModelStores {
    
        private ViewModelStores() {
        }
    
        /**
         * Returns the {@link ViewModelStore} of the given activity.
         *
         * @param activity an activity whose {@code ViewModelStore} is requested
         * @return a {@code ViewModelStore}
         */
        @NonNull
        @MainThread
        public static ViewModelStore of(@NonNull FragmentActivity activity) {
            if (activity instanceof ViewModelStoreOwner) {
                //如果已经存在ViewModelStore,直接返回它
                return ((ViewModelStoreOwner) activity).getViewModelStore();
            }
            //否则,新建一个
            return holderFragmentFor(activity).getViewModelStore();
        }
    
        /**
         * Returns the {@link ViewModelStore} of the given fragment.
         *
         * @param fragment a fragment whose {@code ViewModelStore} is requested
         * @return a {@code ViewModelStore}
         */
        @NonNull
        @MainThread
        public static ViewModelStore of(@NonNull Fragment fragment) {
            if (fragment instanceof ViewModelStoreOwner) {
                return ((ViewModelStoreOwner) fragment).getViewModelStore();
            }
            return holderFragmentFor(fragment).getViewModelStore();
        }
    }
    
    

    只有两个of方法和一个构造方法,只接受FragmentActivity 和Fragment,没骗你吧。

    这里,holderFragmentFor是包内定义好的一个Fragment类,继承于Fragment实现ViewModelStoreOwner接口(里面包含ViewModelStore getViewModelStore();方法,主要就是为了实现这个方法,符合接口隔离原则),HolderFragment的构造方法里面:

    public HolderFragment() {
         setRetainInstance(true);
    }
    

    调用 setRetainInstance(true)了!,没骗你吧

    • holderFragmentFor方法
     /**
         * @hide
         */
        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
        public static HolderFragment holderFragmentFor(FragmentActivity activity) {
            //调用静态内部类HolderFragmentManager的holderFragmentFor
            return sHolderFragmentManager.holderFragmentFor(activity);
        }
    
      ......
      /*省略部分代码,在HolderFragment 里面:*/
       HolderFragment holderFragmentFor(FragmentActivity activity) {
                FragmentManager fm = activity.getSupportFragmentManager();
                HolderFragment holder = findHolderFragment(fm);//获取holder(holder是Fragment)
                //非空立刻返回holder
                if (holder != null) {
                    return holder;
                }
                //mNotCommittedActivityHolders是HolderFragmentManager内部用于存储<Activity, HolderFragment>键值对的变量
                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;
            }
    //新建HolderFragment 
     private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {
                HolderFragment holder = new HolderFragment();
                fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();
                return holder;
            }
    
     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;
            }
    

    findHolderFragment和createHolderFragment代码都比较简单,就不解释了。
    这一步主要就是为了获得HolderFragment,回到ViewModelStores.of方法,接着主要还是要获取它的ViewModelStore,ViewModelStore内部维护了一个HashMap<String, ViewModel>,实现get,put,clear方法,这里就不贴代码了,把它当做Map的一部分就行,主要用于存放ViewModel。
    如此一来,就获取到ViewModelStore了,然后再回到 ViewModelProvider.of里面,将它传递给ViewModelProvider

    return new ViewModelProvider(ViewModelStores.of(activity), factory);
    
    • ViewModelProvider
     public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
            mFactory = factory;
            this.mViewModelStore = store;
        }
    

    ViewModelProvider把这两个家伙给存储起来以供调用,如此一来,刚才那段代码

    ViewModelProviders.of(this).get(TestModel::class.java) 
    

    of到这里就结束了,接下来看get:

     @NonNull
        @MainThread
        public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
            String canonicalName = modelClass.getCanonicalName();//获取ViewModel的名字
            if (canonicalName == null) {
                //如果为空,抛异常
                throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
            }
            //否则获取ViewModel
            //这里DEFAULT_KEY 是默认值,
            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);//从mViewModelStore里面获取viewModel 
            //如果已存在,返回
            if (modelClass.isInstance(viewModel)) {
                //noinspection unchecked
                return (T) viewModel;
            } else {
                //noinspection StatementWithEmptyBody
                if (viewModel != null) {
                    // TODO: log a warning.
                }
            }
            //从工厂里面创建出ViewModel并返回
            viewModel = mFactory.create(modelClass);
            mViewModelStore.put(key, viewModel);
            //noinspection unchecked
            return (T) viewModel;
        }
    

    这里的工厂就是我们传递进来的那个啦,如果不传,则默认会新建一个, ViewModelProvider.of已经说明。
    由此就可以获取到ViewModel啦!

    ViewModel.png

    以上!

    总结

    获取ViewModel的方法

    ViewModelProviders.of(this).get(TestModel::class.java)
    

    分为两个步骤:
    1.of获取到ViewModelProvider,而获取ViewModelProvider需要先获取ViewModelStores
    2.从ViewModelProvider中获取ViewModel
    原创文章,转载请附上https://www.jianshu.com/p/123051a328ba

    相关文章

      网友评论

        本文标题:ViewModel源码解析

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