【Android Jetpack】- ViewModel(源码分析)

简介

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

使用场景1

  • 定义ViewModel类
class ViewModelData : ViewModel(){
    private val viewModel : VMData by lazy {
        VMData().also {
            it.age = 26
            it.name = "丘比特"
        }
    }
}
class VMData{
    var name = ""
    var age = 21
}
  • 使用ViewModelProvider创建ViewModel对象
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 get(@NonNull String key, @NonNull Class 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抽象类,所以这里集中分析这两个类。

  • AbstractSavedStateViewModelFactory
    改类主要有三个变量

    private final SavedStateRegistry mSavedStateRegistry;
    private final Lifecycle mLifecycle;
    private final Bundle mDefaultArgs;
    

    SavedStateViewModelFactory构造体

     public SavedStateViewModelFactory(@NonNull Application application,
             @NonNull SavedStateRegistryOwner owner,
             @Nullable Bundle defaultArgs) {
         super(owner, defaultArgs);
         mApplication = application;
         mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
     }
    

    AbstractSavedStateViewModelFactory构造体

    public AbstractSavedStateViewModelFactory(@NonNull SavedStateRegistryOwner owner,
              @Nullable Bundle defaultArgs) {
          mSavedStateRegistry = owner.getSavedStateRegistry();
          mLifecycle = owner.getLifecycle();
          mDefaultArgs = defaultArgs;
    }
    

    mSavedStateRegistry,mLifecycle都是AppCompatActivity对象返回,mDefaultArgs是AppCompatActivity的持有的Bundle对象。mFactory是ViewModelProvider.AndroidViewModelFactory单例。

    • 创建ViewModel 对象
      调用AbstractSavedStateViewModelFactory的create方法

      public final  T create(@NonNull String key, @NonNull Class modelClass) {
          // 消耗先前提供的保存状态,之前存储的Bundle对象
          Bundle restoredState = mSavedStateRegistry.consumeRestoredStateForKey(key);
          // 将之前的保存状态和现在进行合并,放到SavedStateHandle中的一个数组里
          SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, mDefaultArgs);
          // 创建持有key和handle的SavedStateHandleController对象
          SavedStateHandleController controller = new SavedStateHandleController(key, handle);
          // 添加监听和注册SavedStateProvider到SavedStateRegistry里
          controller.attachToLifecycle(mSavedStateRegistry, mLifecycle);
          // 创建viewmodel对象
          T viewmodel = create(key, modelClass, handle);
         // 保存controller到viewmodel实例中
        viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
          // 创建拥有组件重新启动时执行类的对象
          mSavedStateRegistry.runOnNextRecreation(OnRecreation.class);
          return viewmodel;
      }
      

      runOnNextRecreation方法

      public void runOnNextRecreation(@NonNull Class clazz) {
         ...
          if (mRecreatorProvider == null) {
              mRecreatorProvider = new Recreator.SavedStateProvider(this);
          }
          ...
          mRecreatorProvider.add(clazz.getName());
      }
      

      SavedStateProvider构造体

      SavedStateProvider(final SavedStateRegistry registry) {
              registry.registerSavedStateProvider(COMPONENT_KEY, this);
      }
      

      向SavedStateRegistry对象注册直接,key = COMPONENT_KEY。

    • AppCompatActivity调用

      protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mSavedStateRegistryController.performRestore(savedInstanceState);
         ...
       }
      
      protected void onSaveInstanceState(@NonNull Bundle outState) {
        ...
        mSavedStateRegistryController.performSave(outState);
      }
      
    • SavedStateRegistryController

      public void performRestore(@Nullable Bundle savedState) {
        Lifecycle lifecycle = mOwner.getLifecycle();
       ...
        lifecycle.addObserver(new Recreator(mOwner));
        mRegistry.performRestore(lifecycle, savedState);
      }
      
      public void performSave(@NonNull Bundle outBundle) {
          mRegistry.performSave(outBundle);
      }
      
    • 使用
      定义ViewModel

      class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel(){
          private val viewModel : VMData by lazy {
              VMData().also {
                  it.age = 26
                  it.name = "丘比特"
              }
          }
      }
      
    • 创建ViewModel

      private fun savedStateModel(){
         val vm = ViewModelProvider(this, SavedStateViewModelFactory(application,this)).get(SavedStateViewModel::class.java)
         val vm1 = ViewModelProvider(this, defaultViewModelProviderFactory).get(SavedStateViewModel::class.java)
      }
      

你可能感兴趣的:(【Android Jetpack】- ViewModel(源码分析))