ViewModel分析

2020-04-03  本文已影响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来通信

上一篇下一篇

猜你喜欢

热点阅读