美文网首页
ViewModel分析

ViewModel分析

作者: 谜夨_ | 来源:发表于2020-04-03 19:54 被阅读0次

    Q群的被迫作业这里就写一写

    写在前面

    首先在官方文档里面,他表明了我们一般在oncreate()里初始化,也就是viewmodel实例化的地方。

    ViewModelProvider的初始化:

    (VM) ViewModelProviders.of(this)这是以前的初始化现在这个方法已经被不推荐使用了。
    如果你看过之前版本的源码会发现和现在已经有些许不同了。
    现在你直接使用new ViewModelProvider(activity)原本的不推荐使用的方法也被修改了。

        //用判断是否有默认的factory
        //当然你也可以直接塞入一个factory 如果你的viewmodel需要传入一些参数的话
        public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
            this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                    ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                    : NewInstanceFactory.getInstance());
        }
    
        public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
            this(owner.getViewModelStore(), factory);
        }
    
    

    先讲NewInstanceFactory

         public static class NewInstanceFactory implements Factory {
            private static NewInstanceFactory sInstance;
    
            //获得单例
            @NonNull
            static NewInstanceFactory getInstance() {
                if (sInstance == null) {
                    sInstance = new NewInstanceFactory();
                }
                return sInstance;
            }
    
            //反射创建 这里因为是默认的就没有穿参
            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);
                }
            }
        }
    

    这里有个新的类ViewModelStore
    ViewModelStore 内部维护了一个 HashMap,其 key 为 DEFAULT_KEY + ViewModelClass对象底层类规范名称,其 value 为对应 ViewModel 对象。每个 ActivityFragment 都对应着一个 ViewModelStore ,用于存储所需的 ViewModel

        @NonNull
        @Override
        public ViewModelStore getViewModelStore() {
            if (getApplication() == null) {
                throw new IllegalStateException("Your activity is not yet attached to the "
                        + "Application instance. You can't request ViewModel before onCreate call.");
            }
            if (mViewModelStore == null) {
                //此处为是否需要回复viewmodel 后面会讲到
                NonConfigurationInstances nc =
                        (NonConfigurationInstances) getLastNonConfigurationInstance();
                if (nc != null) {
                    // Restore the ViewModelStore from NonConfigurationInstances
                    mViewModelStore = nc.viewModelStore;
                }
                if (mViewModelStore == null) {
                    mViewModelStore = new ViewModelStore();
                }
            }
            return mViewModelStore;
        }
    

    之后 Activity 中创建与获取 ViewModel

        @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");
            }
            //这里就是值钱说的默认的key
            return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
        }
    
        @NonNull
        @MainThread
        public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
           //根据key值从 ViewModelStore 中取对应的 ViewModel
            ViewModel viewModel = mViewModelStore.get(key);
            //判断Class对象是否是ViewModel的Class类或其子类的对象
            if (modelClass.isInstance(viewModel)) {
                if (mFactory instanceof OnRequeryFactory) {
                    ((OnRequeryFactory) mFactory).onRequery(viewModel);
                }
                return (T) viewModel;
            } else {
                //noinspection StatementWithEmptyBody
                if (viewModel != null) {
                    // TODO: log a warning.
                }
            }
            //factory创建viewmodel
            if (mFactory instanceof KeyedFactory) {
                viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
            } else {
                viewModel = (mFactory).create(modelClass);
            }
            //再把viewmodel保存金 viewModelStrore
            mViewModelStore.put(key, viewModel);
            return (T) viewModel;
        }
    

    标注自己看 我下面有张WINDOWS画图制作的图讲究下看吧
    activity举个例子

    我觉得我画的很好

    Viewmodel 状态保存

    一张谁都见过的图.jpg

    Activity可能被重新创建,哪吗viewmodel是如何保存的那
    一般来说需要恢复数据的部分有两种,一种activity被其他资源优先级卡死了,一种是配置变了activity被干掉重建了。

    在上面我们说到过activity会持有ViewModelStore,在ComponentActivity中有一个方法叫onRetainNonConfigurationInstance在该方法中保存了ViewModel
    真正销毁之前ActivityThread会调用activityretainNonConfigurationInstances——>onRetainNonConfigurationInstance

        @Override
        @Nullable
        public final Object onRetainNonConfigurationInstance() {
            Object custom = onRetainCustomNonConfigurationInstance();
    
            ViewModelStore viewModelStore = mViewModelStore;
            if (viewModelStore == null) {
                // No one called getViewModelStore(), so see if there was an existing
                // ViewModelStore from our last NonConfigurationInstance
                NonConfigurationInstances nc =
                        (NonConfigurationInstances) getLastNonConfigurationInstance();
                if (nc != null) {
                    viewModelStore = nc.viewModelStore;
                }
            }
    
            if (viewModelStore == null && custom == null) {
                return null;
            }
    
            NonConfigurationInstances nci = new NonConfigurationInstances();
            nci.custom = custom;
            nci.viewModelStore = viewModelStore;
            return nci;
        }
    

    那之前是保存恢复的话记得上面之前的ViewModelStores吗我标记了.

    ViewModel 何时判断是否被移除

    上图中很明显的标识在ondestory()之后会onClear()

         //ComponentActivity构造方法中
          getLifecycle().addObserver(new LifecycleEventObserver() {
                @Override
                public void onStateChanged(@NonNull LifecycleOwner source,
                        @NonNull Lifecycle.Event event) {
                    if (event == Lifecycle.Event.ON_DESTROY) {
                        //mChangingConfigurations 这个值用来判断是否真的需要被移除 不是重启有兴趣可以自行阅读源码 我以后再写
                        if (!isChangingConfigurations()) {
                            getViewModelStore().clear();
                        }
                    }
                }
            });
    
         /**
         *  Clears internal storage and notifies ViewModels that they are no longer used.
         */
        public final void clear() {
            for (ViewModel vm : mMap.values()) {
                vm.clear();
            }
            mMap.clear();
        }
    

    这样被移除了之后就会被回收拉在下次回收,因为GC是不回回收强引用的,所以在官方文档中强调了.
    ViewModel 不应持有 ViewLifecycle、或其他可能持有 ActivityContext 的类的引用。

    不过总有人喜欢,他也给里面留了条后路,可以在onclear()去释放他们,不过官方还是强烈建议使用livedata来通信

    相关文章

      网友评论

          本文标题:ViewModel分析

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