美文网首页
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来通信

相关文章

  • Android Jetpack之ViewModel源码分析

    Android Jetpack之ViewModel源码分析 ViewModel 简介 在Android开发的时候,...

  • Android Jetpack 架构组件之 ViewModel

    Android Jetpack 架构组件之 ViewModel 源码分析 1. 认识 ViewModel 1.1....

  • ViewModel分析

    ViewModel的主要作用:1、当界面横竖屏切换的时候,如果页面中有状态需要保存,那么可以通过ViewModel...

  • ViewModel分析

    Q群的被迫作业这里就写一写 写在前面 首先在官方文档里面,他表明了我们一般在oncreate()里初始化,也就是v...

  • Jetpack 之 ViewModel 原理

    ViewModel 源码分析 入口 四种方式创建ViewModel,最终生成ViewModelStore进行存储 ...

  • 电商购物(MVVM+ReactiveCocoa)

    导语 使用RAC实践购物车逻辑的梳理!首先分析ViewModel里面的每一个属性,然后分析ViewModel里面的...

  • ViewModel 源码分析

    简单介绍 从图可以看出来,ViewModel 与 LiveData 和 Paging 是谷歌新组件,同时它是 an...

  • ViewModel源码分析

    ViewModel是什么?ViewModel是负责管理Activity和Fragment的数据的类,他独立于Act...

  • ViewModel原理分析

    2020年最后一篇,哈哈。 本篇文章主要分析ViewModel在Activity从销毁到重建时是如何保存并恢复的。...

  • ViewModel源码分析

    一、ViewModel的简介 2018年谷歌IO大会上正式发布了JetPack组件,其中包括Databing、Li...

网友评论

      本文标题:ViewModel分析

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