深入解析ViewModel是如何在配置更改后继续留存数据的

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据,ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。

那么我们今天就探索下,配置更改后,是如何继续留存数据的。

首先我们看下如何创建ViewModel实例:

class CustomFactory : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return when (modelClass) {
            MainViewModel::class.java -> {
                MainViewModel()
            }
            else -> throw IllegalArgumentException("Unknown class $modelClass")
        } as T
    }
}

创建ViewModel实例

// 1
val viewModelProvider = ViewModelProvider(this, CustomFactory())
// 2
val viewModel: MainViewModel= viewModelProvider.get(MainViewModel::class.java)
// 或者使用KTX来创建
//val model : MainViewModel by viewModels { CustomFactory() }

ViewModelProvider源码

public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull ViewModelProvider.Factory factory) {
     // 3
    this(owner.getViewModelStore(), factory);
}

public ViewModelProvider(@NonNull ViewModelStore store, @NonNull ViewModelProvider.Factory factory) {
    this.mFactory = factory;
    this.mViewModelStore = store;
}

ViewModelStoreOwner源码

public interface ViewModelStoreOwner {
    @NonNull
    ViewModelStore getViewModelStore();
}

看看上面这段代码做了什么:

  1. 首先创建一个ViewModelProvider实例,ViewModelProvider构造函数的第一个参数是ViewModelStoreOwner,那为什么可以传入Activity实例呢,是因为ComponentActivity实现了ViewModelStoreOwner这个接口;

  2. 通过 get(@NonNull Class<T> modelClass) 方法 获取到 ViewModel 的实例;

  3. 通过 owner.getViewModelStore()获取到 ViewModelStore,也就是ComponentActivitygetViewModelStore()方法。

然后我们看下ViewModelProvider#get()方法:

@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");
    } else {
        return this.get("androidx.lifecycle.ViewModelProvider.DefaultKey:" + canonicalName, modelClass);
    }
}

@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    ViewModel viewModel = this.mViewModelStore.get(key);
    if (modelClass.isInstance(viewModel)) {
        if (this.mFactory instanceof ViewModelProvider.OnRequeryFactory) {
            ((ViewModelProvider.OnRequeryFactory)this.mFactory).onRequery(viewModel);
        }

        return viewModel;
    } else {
        if (viewModel != null) {
        }

        if (this.mFactory instanceof ViewModelProvider.KeyedFactory) {
            viewModel = ((ViewModelProvider.KeyedFactory)this.mFactory).create(key, modelClass);
        } else {
            viewModel = this.mFactory.create(modelClass);
        }

        this.mViewModelStore.put(key, viewModel);
        return viewModel;
    }
}

从在上面的代码中可以发现,ViewModelStore中持有一个HashMap,如果ViewModelStore中有缓存的ViewModel实例,就直接返回,否则创建新的实例并存入到ViewModelStore中。

接下来我们看下 ComponentActivity#getViewModelStore()方法:

@NonNull
public ViewModelStore getViewModelStore() {
    if (this.getApplication() == null) {
        throw new IllegalStateException("Your activity is not yet attached t
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值