viewmodel的存取流程

一:获取view model的代码

public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);//从一个hash map中用key取view model,key是view model的类名。

        if (modelClass.isInstance(viewModel)) {//如果还没有view model实例,即上一步得到null, 那么就不会进去,如果进入了,就会返回view mdoel了
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel; //返回view model
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);//创建view model
        } else {
            viewModel = mFactory.create(modelClass);//创建view model
        }
        mViewModelStore.put(key, viewModel);//往map里面插入这个view model
        return (T) viewModel;
    }

activity实现了view model store owner,拥有view model store,view model store则拥有一个map存放view model。

但是当配置更改时,view model store实例如何才能保证是旧的那个呢?

二:如何不改变view model store

首先来看看activity如何获取view model store

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) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();//这个重点
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }

因为activity创建时view model store都是null,当我们第一次取时,会看看nc,如果nc不为null,代表nc存有以前的view model,就取出来就行了,没有就创建。

所以关键是,这个nc是什么,它是如何保存我们之前的viewmodel的,为森马它不为空,就存有旧 viewmodel呢?

搞明白这个nc,就知道view mdoel store是如何不变的了。

三:搞明白NonCon.....Instances如何存

在上一段代码中,ComponenetActivity.java的getViewModelStore方法会调用Activity.java的getLastNCI方法,getLastNCI方法会返回Activity.java内部的一个NCI对象

static final class NonConfigurationInstances {
        Object activity;
        。。。。。
    }

那为什么这个对象会存有我们的viewmdoelstore实例呢?

原因就是:

当Activity.java销毁的时候,会保存Activity.NCI实例:

Activity,java

NonConfigurationInstances retainNonConfigurationInstances() {
        Object activity = onRetainNonConfigurationInstance();
       ......

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.activity = activity;
      
        return nci;
    }


ComponentActivity.java

public final Object onRetainNonConfigurationInstance() {
       
        ViewModelStore viewModelStore = mViewModelStore;
       ......
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.viewModelStore = viewModelStore;
        return nci;
}

activity销毁的时候,系统会调用retainXXXX,然后调用 onRetainXXXX,把view model store存进去了,把ComponentActivity.java的NCI对象存到Activity.java的NCI对象的一个叫做“activity”的变量里面,这个变量名十分误导人,叫其他不好吗?叫store也好啊!!

四:搞明白NonCon.....Instances如何恢复

系统调用Activity.java的attach方法

Activity.java

final void attach( NonConfigurationInstances lastNonConfigurationInstances){

...
mLastNonConfigurationInstances = lastNonConfigurationInstances
...
}

这样呢,在第二部分 ComponentActivity.java获取viewmdoelstore的方法里就可以获取到这个NCI了。

整体流程如下

参考:https://blog.mindorks.com/android-viewmodels-under-the-hood

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值