Android开发规范技巧

【Android Jetpack】- ViewModel(源码分

2019-10-20  本文已影响0人  拔萝卜占坑

简介

ViewModel类旨在以生命周期感知的方式存储和管理与UI相关的数据。

使用场景1

class ViewModelData : ViewModel(){
    private val viewModel : VMData by lazy {
        VMData().also {
            it.age = 26
            it.name = "丘比特"
        }
    }
}
class VMData{
    var name = ""
    var age = 21
}
val vmData = ViewModelProvider.AndroidViewModelFactory(application).create(ViewModelData::class.java)
// 这个区别是AndroidViewModelFactory是单例
val  vmData1 = ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(ViewModelData::class.java)

这是最基本的时候方式,使用ViewModelProvider来提供ViewModel对象。通过查看源码可以得知。这种方式每使用一次就会产生一个ViewModel对象。

这样看上去ViewModel的用处并不是很大,根据官网的建议,我们可以把加载数据的逻辑放在ViewModel里面,替代以前的Loaders模块。

  1. 不使用ViewModel


    屏幕快照 2019-10-20 下午8.58.50.png
  2. 使用ViewModel


    屏幕快照 2019-10-20 下午8.58.56.png

使用场景2 — Fragment之间的数据共享

通过查看ViewModelProvider源码,发现ViewModelProvider可以通过get方法来获取ViewModel。

public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
       ViewModel viewModel = mViewModelStore.get(key);
       if (modelClass.isInstance(viewModel)) {
           return (T) viewModel;
       } else {
          ...
       }
       ...
      if (mFactory instanceof KeyedFactory) {
           viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
       } else {
           viewModel = (mFactory).create(modelClass);
       }
       mViewModelStore.put(key, viewModel);
       return (T) viewModel;
}

如果想不同Fragment直接拿到是相同的ViewModel,那么就得保证mViewModelStore唯一,mViewModelStore是ViewModelStore实例,源码很简单,自行查看。

class ViewModelActivity: AppCompatActivity(){
    ...
   // Fragment直接的数据共享
    private fun fragmentShare(){
        val vm = ViewModelProvider(this).get(ViewModelData::class.java)
        // ViewModelProviders已经被抛弃
        val vm1 = ViewModelProviders.of(this)[ViewModelData::class.java]
    }
}

看一下构造体

public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
}

owner就是AppCompatActivity对象,而AppCompatActivity实现了HasDefaultViewModelProviderFactory和ViewModelStoreOwner接口。那这里得到的Factory和ViewModelStore就是AppCompatActivity返回的。

public ViewModelStore getViewModelStore() {
       ...
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
}

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
        ...
        if (mDefaultFactory == null) {
            mDefaultFactory = new SavedStateViewModelFactory(
                    getApplication(),
                    this,
                    getIntent() != null ? getIntent().getExtras() : null);
        }
        return mDefaultFactory;
}

如果是同一个AppCompatActivity,那么Factory和ViewModelStore便是唯一的,自然就可以在Fragment之间共享数据了。

使用场景3 - 状态的备份和恢复

如“保存UI状态”文章中所述,ViewModel对象可以处理配置更改,因此您不必担心轮换或其他情况下的状态。但是,如果需要处理系统启动的进程终止,则可能要使用onSaveInstanceState作为备份。

在场景2中,创建的ViewModelProvider是一个SavedStateViewModelFactory对象,那么我们来看看SavedStateViewModelFactory实现了什么功能。SavedStateViewModelFactory继承了AbstractSavedStateViewModelFactory抽象类,所以这里集中分析这两个类。

上一篇 下一篇

猜你喜欢

热点阅读