ViewModel源码分析

ViewModel源码分析

学习过ViewModel的都知道,ViewModel主要对数据进行存储维护,当在异常情况下(横竖屏)Activity被销毁的时候恢复数据。

Android异常情况下维护数据的方法

  • Activity.onSaveInstanceState和Activity.onRestoreInstanceState
  • FragmentActivity.onRetainNonConfigurationInstance和FragmentActivity.getLastNonConfigurationInstance
  • Fragment.setRetainInstance()的特性

在Android中想要维护异常销毁Activity都是通过以上三种方法,因为方法一需要序列化的缘故,大数据的数据恢复我们一般用后面两种方法,了解了这些简单的知识点后,接下来我们来看看ViewModel的源码。

FragmentActivity保存和恢复数据的流程

让我们先来看看获取ViewModel的入口代码:

	1.FragmentActivity
    final ProjectViewModel viewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(ProjectViewModel.class);
	
	2.ViewModelProviders
	public static ViewModelProvider of(@NonNull FragmentActivity activity,
        	@Nullable Factory factory) {
    	...
    	return new ViewModelProvider(activity.getViewModelStore(), factory);
	}

代码块1使用ViewModelProviders.of静态方法创建ViewModelProvider的对象,这里我们先不考虑activity.getViewModelStore()的逻辑,继续看下去,然后调用其ViewModelProvider.get方法:

public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
    String canonicalName = modelClass.getCanonicalName();
   	...
    return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}

public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
	1.从ViewModelStore获取ViewModel
    ViewModel viewModel = mViewModelStore.get(key);

    if (modelClass.isInstance(viewModel)) {
        2.取出的对象不为null 并且 为 传入的Class直接返回
        return (T) viewModel;
    } else {
        ..
    }
	3.在工厂类中获取到新的ViewModel对象,并保存在ViewModelStor中
    viewModel = mFactory.create(modelClass);
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}

以上获取ViewModel的流程我们可以总结为:

  • 先尝试从ViewModelStore根据相关的Key获取到ViewModel对象
  • 假如能够获取到,并且是我们需要的对象则直接返回
  • 假如不能获取到,那么就使用工厂类创建新的ViewModel对象,并且保存到ViewModelStore中维护

到这里我们可以尝试着看看ViewModelStore是一个什么类?

public class ViewModelStore {
	private final HashMap<String, ViewModel> mMap = new HashMap<>();
	final void put(String key, ViewModel viewModel) {
    	...
	}
	final ViewModel get(String key) {
    	...
	}
	public final void clear() {
    	...
	}
}

从类名我们就可以看出来,这个类的功能主要是:为了存储ViewModel,其内部核心就是使用HashMap对ViewModel进行管理,其对象的获取办法我们回到上面的 ViewModelProviders.of() 查看:activity.getViewModelStore()

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

从上面的代码片段我们可以看出大致的逻辑流程为:

  • 判断假如ViewModelStore为空,那么就从FragmentActivity.getLastNonConfigurationInstance获取NonConfigurationInstances对象,然后获取到保存的ViewModelStore
  • 否则直接返回ViewModelStore对象

以上就是获取ViewModelStore的流程,既然有恢复数据的流程,那么就要看一下保存数据的流程,保存数据的按照原理是在FragmentActivity
.onRetainNonConfigurationInstance()中:

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

从代码中可知,当出现异常情况销毁时onRetainNonConfigurationInstance()方法会被调用保存数据对象,然后在FragmentActivity.getLastNonConfigurationInstance被调用的时候进行恢复数据。

最终当Activity进行销毁时会调用FragmentActivity.onDestroy()方法,假如当前不是屏幕滚动导致的销毁,那么ViewModelStore会被清理资源:

protected void onDestroy() {
    super.onDestroy();
    if (mViewModelStore != null && !isChangingConfigurations()) {
        mViewModelStore.clear();
    }

}

Fragment

Fragment的原理稍微简单点,其实就是直接创建ViewModelStore对象进行维护ViewModel,利用Fragment.setRetainInstance()的特性让在Fragment的ViewModelStore对象在Activity横竖屏翻滚的时候不进行回收对象的处理

Factory类

public interface Factory {
    @NonNull
    <T extends ViewModel> T create(@NonNull Class<T> modelClass);
}

Factory类是一个对象,定义了创建ViewModel的协议接口,ViewModel框架提供了两个实现类NewInstanceFactoryAndroidViewModelFactory,使用的是Class反射创建对象。

总结

  • Activity使用FragmentActivity.onRetainNonConfigurationInstance和FragmentActivity.getLastNonConfigurationInstance的特性进行保存和恢复数据
  • Fragment使用Fragment.setRetainInstance()的特性进行保存和恢复数据
  • ViewModelStore的作用是维护ViewModel对象
  • Factory工厂类的作用是产生ViewModel对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值