前语:本年的龙舟雨来了,一场接一场,雨量很大。
前语
以往假如需求在Activity
或者Fragment
中保存数据状况则需求重写onSaveInstanceState ,运用bundle去存储相应的数据和状况,可是这也只能保存轻量简略的序列化数据。而 ViewModel
能够做到在装备改变后仍然持有状况。
现在的 MVVM 架构模式中,将View数据与逻辑放在ViewModel
中(即 MVP 中的Presenter),而 ViewModel 是不需求持有UI层引证的(由于 ViewModel 的生命周期更长),然后对外暴露观察者,一般是搭配LiveData
一同运用,以此更简单的保持状况同步。那么就避免了或许的内存走漏,同时完结了解耦。
一、什么是ViewModel
ViewModel作为JetPack中心组件,它的完结远没有咱们幻想的那么简略。 ViewModel类是一种事务逻辑或屏幕级状况容器。简略理解便是为UI层供给数据,以及封装相关的事务逻辑。
它的首要长处是,它能够缓存状况,并可在装备更改后持久保留相应状况。这意味着在 Activity 之间导航时或进行装备更改后(例如旋转屏幕时),界面将无需从头恳求数据。
- 具备宿主生命周期感知能力的数据存储组件(它只能感知宿主被毁掉的事情);
- ViewModel 保存的数据,在页面因装备改变导致页面毁掉重建之后仍然存在的。
装备改变
装备改变是指使用内的装备参数改变然后触发的 Activity 从头创立。
常见的装备改变场景:反正屏切换、分辨率调整、权限改变、体系字体款式改变等。
生命周期
关于ViewModel的生命周期,详细如下图所示:

ViewModel 最重要的特点是生命周期长于Activity。它只能感知宿主被毁掉的事情(onDestory),能够复写 onCleared()
来做一些清理和释放的作业。(Fragment的生命周期也是同理)
二、ViewModel的用法
先来了解一下怎么运用 ViewModel。
1.常规用法
ViewModel 存储的数据,仅仅只能当页面由于装备改变导致的毁掉再重建时复用。复用的是 ViewModel 的实例目标整体。
ViewModel 层恳求数据,处理事务逻辑:
class MainViewModel : ViewModel() {
val userLiveData = MutableLiveData<String>()
fun getUserInfo() {
//为了适配因装备改变而导致的页面重建,重复使用之前的数据,加速新页面渲染,不在恳求接口
//假如value不为空,说明这个ViewModel肯定是复用的,由于新建的ViewModel的liveData是不会有数据的
if (userLiveData.value == null) {
// 模拟恳求接口回来数据
viewModelScope.launch {
delay(1000)
userLiveData.postValue("苏火火 苏火火 苏火火 苏火火 苏火火")
}
}
}
}
UI层处理显示逻辑:
class MainActivity : BaseDataBindActivity<ActivityViewmodelBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
LogUtil.d("onCreate()")
//经过ViewModelProvider来获取ViewModel目标
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
//注册监听,监听数据的回调
viewModel.userLiveData.observe(this, Observer {
//接收到数据
dismissLoading()
mBinding.tvUserInfo.text = it
})
mBinding.tvRequestUserInfo.onClick {
// 恳求数据
showLoading()
viewModel.getUserInfo()
}
}
override fun onStop() {
super.onStop()
LogUtil.d("onStop()")
}
override fun onDestroy() {
super.onDestroy()
LogUtil.d("onDestroy()")
}
}
生命周期打印数据如下:
/com.sum.tea D/LogUtil: onStop() /com.sum.tea D/LogUtil: onDestroy() /com.sum.tea D/LogUtil: onCreate()

2.单Activity多Fragment数据共享
Activity 中的多个 Fragment 需求彼此通讯是一种很常见的状况。以往通讯的办法有接口,ResultAPI,EventBus,广播等多种办法,而 ViewModel 也能够完结一个 Activity 与其间的多个 Fragment 之间的彼此通讯。
//获取数据
class UserFragment : BaseDataBindFragment<FragmentMainBinding>() {
override fun initView(view: View, savedInstanceState: Bundle?) {
val viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
// 获取ViewModel,留意传入的是宿主Activity
viewModel.userLiveData.observe(this) {
mBinding?.tvTitle?.text = "UserFragment \n\n $it"
}
}
}
//发送数据
class VideoFragment : BaseDataBindFragment<FragmentMainBinding>() {
override fun initView(view: View, savedInstanceState: Bundle?) {
// 获取ViewModel,留意传入的是宿主Activity
val viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
viewModel.shareLiveData.value = "数据共享:VideoFragment中的数据"
}
}

3.跨页面数据共享
还能够运用它跨页面跨 Activity 数据共享,只要 Application 完结 ViewModelStoreOwner 就能够了,其他页面经过 application 获取 ViewModel:
//让Application完结ViewModelStoreOwner接口
class SumApplication : Application(), ViewModelStoreOwner {
private val appViewModelStore: ViewModelStore by lazy {
ViewModelStore()
}
override fun getViewModelStore(): ViewModelStore {
return appViewModelStore
}
}
//其他页面经过application获取viewModel
val viewModel = ViewModelProvider(application).get(MainViewModel::class.java)
源码地址:github.com/suming77/Su…
假如是正常关闭一个页面,ViewModel 的数据仍是正常被关闭被清理的。有人会疑惑,页面都被毁掉了,为什么数据还持续存在?实践上是 ViewModel 被保存了下来,页面被重建之后,咱们在获取 ViewModel 实例的时分实践上仍是同一个,然后到达里边数据的复用。
三、ViewModel的完结原理
很多人说 ViewModel 完结原理都是说成 ViewModel 是怎么完结数据复用的,其实这种说法是不行精确的,由于 ViewModel 能够完结数据复用,本质上是 ViewModel 的实例目标得到了复用。精确点来说是 ViewModel 在宿主毁掉了,还能持续存在。以至于页面恢复重建后,还能接着复用。(肯定是前后获取到的是同一个 ViewModel 实例目标)
先来知道 ViewModel 中几个重要的类:
- ViewModelProvider: 供给获取 ViewModel 实例的类,ViewModel 都是从这个类中获取。
-
ViewModelStoreOwner:中心接口,该接口的完结类表示能够为外部供给
ViewModelStore
实例。 - ViewModelStore: 中心类,存储 ViewModel 实例的类,实践是一个HashMap。
- Factory: 中心接口,担任创立 ViewModel 实例。
假如要剖析 ViewModel 复用的原理,就要从怎么获取 ViewModel 的实例说起。
1.ViewModel的存储和获取
获取 ViewModel 的实例进程:
val viewModel = ViewModelProvider(activity).get(HiViewModel::class.java)
ViewModelProvider 类有三个结构函数,不管你运用的是哪个结构函数,最后都会调用ViewModelProvider(ViewModelStore store, Factory factory)
:
#ViewModelProvider.java
public ViewModelProvider(ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(ViewModelStoreOwner owner, Factory factory) {
this(owner.getViewModelStore(), factory);
}
public ViewModelProvider(ViewModelStore store, Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
在创立 ViewModelProvider 的时分,参数虽然是 Activity,实践上这儿要求的是 ViewModelStoreOwner,那是由于 Activity 也便是 ComponentActivity 它完结了 ViewModelStoreOwner 这个接口的,而且复写了 getViewModelStore()
办法,然后把 Store 和 Factory 两个参数保存了起来:
public interface ViewModelStoreOwner {
//获取ViewModelStore
ViewModelStore getViewModelStore();
}
这个 ViewModelStore 便是用来存储 ViewModel 实例的,它本质上便是一个 HashMap,十分简略:
//用于存储ViewModel实例
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
// 保存viewModel实例
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
//清除ViewModel
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
假如不传递 Factory 参数则会有个默认的,Factory 便是用来创立 ViewModel 实例的,当咱们从 ViewModelStore 里边获取 ViewModel 实例的时分,假如获取不到,就会经过 Factory 来创立它,待会来剖析它,持续看 ViewModelProvider
的 get 办法:
#ViewModelProvider.java
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
//拿到Key,即ViewModelStore中的Map用于存ViewModel的Key
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
private static final String DEFAULT_KEY =
"androidx.lifecycle.ViewModelProvider.DefaultKey";
经过 canonicalName 和 DEFAULT_KEY 字段拼接成一个字符串,然后形成一个完好的 Key 字段,便是在 ViewModelStore 里边存储 ViewModel 的 key:
#ViewModelProvider.java
@MainThread
public <T extends ViewModel> T get(String key, Class<T> modelClass) {
//依据key从ViewModelStore中获取ViewModel实例
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
// 假如有这个实例则回来
return (T) viewModel;
}
// 依据mFactory的类型来创立ViewModel实例
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
// 存储到ViewModelStore中
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
回到第一个结构函数中:
ViewModelProvider类
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
getDefaultViewModelProviderFactory()
实践是 SavedStateViewModelFactory:
SavedStateViewModelFactory类:
@Override
public <T extends ViewModel> T create(String key, Class<T> modelClass) {
// 判别是否为AndroidViewModel
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor<T> constructor;
// 获取结构器
if (isAndroidViewModel && mApplication != null) {
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
// 一般办法创立ViewModel实例
if (constructor == null) {
return mFactory.create(modelClass);
}
try {
T viewmodel;
if (isAndroidViewModel && mApplication != null) {
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
viewmodel = constructor.newInstance(controller.getHandle());
}
return viewmodel;
}
创立的时分判别 modelClass 是否具有两种结构函数:
//第一种:有两个参数
private static final Class<?>[] ANDROID_VIEWMODEL_SIGNATURE = new Class[]{Application.class,
SavedStateHandle.class};
//第二种:只要一个参数
private static final Class<?>[] VIEWMODEL_SIGNATURE = new Class[]{SavedStateHandle.class};
假如上面两种都没有,那个在结构实例的时分,就会以一般的办法结构实例 AndroidViewModelFactory,实践上是经过反射。
if (constructor == null) {
return mFactory.create(modelClass);
}
而 NewInstanceFactory 则是一个简略的创立工厂,依据空结构函数,直接经过 Class 直接创立一个 ViewModel 实例:
public static class NewInstanceFactory implements Factory {
@Override
public <T extends ViewModel> T create(@Class<T> modelClass) {
// 经过modelClass反射获取ViewModel实例
return modelClass.newInstance();
}
}
首要经过 mViewModelStore 依据 key 获取 ViewModel 实例,还会判别该实例是不是传入的 Class 类型的,假如是则直接回来,假如不是则会依据 mFactory 是什么类型的,来决定是用什么创立办法来创立 ViewModel 实例,创立完结后存储到 ViewModelStore 中。这便是 ViewModel 实例的存储和获取进程。
2.ViewModelStore的存储和获取
ViewModel 实例是用 ViewModelStore 来获取的,已然要做到 ViewModel 实例的复用,那么 ViewModelStore 它也必须做到复用才能够,要害点就在这儿,ViewModelStore 是在 ComponentActivity 里边被获取的:
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory {
public ViewModelStore getViewModelStore() {
// 假如存储器为空则从NonConfigurationInstances中获取
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
//从NonConfigurationInstances中恢复ViewModelStore
mViewModelStore = nc.viewModelStore;
}
// 假如获取不到,则直接创立一个
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
}
留意了,首要经过 NonConfigurationInstances 获取 ViewModelStore,假如 NonConfigurationInstances 不存则创立一个 ViewModelStore 实例。那么 NonConfigurationInstances 是什么?
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
NonConfigurationInstance s目标本质上是一个包装类,包装一些在装备改变后还想留存的数据,比如说 Fragment,假如一个 Activity 上面有一个 Fragment,咱们的页面在旋转了今后,Activity 会被重建,Fragment 仍是原来的哪一个,这儿的完结原理便是经过 NonConfigurationInstances 来完结的,那么 ViewModel 的复用也是同样的原理。
可是 ViewModel 目标的存储产生在什么时分呢?要先存储了才能够完结复用,实践产生在 onRetainNonConfigurationInstance()
办法里边:
#ComponentActivity.java
@Override
// 在Activity因装备改变而毁掉再重建Activity时,此办法会被调用
// 因装备改变而被毁掉而保存的数据,在重建的时分还想持续复用
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// 测验从NonConfigurationInstance获取ViewModelStore
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
// 假如 viewModelStore == null 则直接回来null
if (viewModelStore == null && custom == null) {
return null;
}
// viewModelStore不为空则构建了一个NonConfigurationInstances目标,而且把viewModelStore存了进去。
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
重点来了,在 Activity 因装备改变而要毁掉时,且会从头创立 Activity,体系就会调用这个办法。 也就说,装备改变时体系把 viewModelStore 存在了 NonConfigurationInstances 中。
跟进 onRetainNonConfigurationInstance()
,它是复写父类的,在 Activity 里边找到调用它的时机:
#Activity.java
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
//
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;
}
重要的是retainNonConfigurationInstances()
这个办法的调用进口在哪里呢?这个是无法在IDE中查看的,它实践是在 ActivityThread 里边。
3.Activity的重建流程
正常发动一个 Activity 的时分,它会在履行 ActivityThread 的 handleLaunchActivity()
,可是一个页面由于装备改变而重建的时分它履行 handleRelaunchActivity()
办法,这个办法是从头创立 Avtivity 的一个进口,可是它正在创立的办法是在里边的 handleRelaunchActivityInner
:
#ActivityThread.java
//由于装备改变而重建的时分会履行
@Override
public void handleRelaunchActivity(ActivityClientRecord tmp,
PendingTransactionActions pendingActions) {
//
//mActivities里边存储的便是当时使用当时进程所已经打开的一切Activity信息的调集
ActivityClientRecord r = mActivities.get(tmp.token);
// 从头创立Activity履行
handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
//
}
mActivities 里边存储的便是当时使用当时进程所已经打开的一切 Activity 信息的调集,经过 mActivities 调集获取到一个
ActivityClientRecord,它里边有个重要的参数lastNonConfigurationInstances
:
public static final class ActivityClientRecord {
//
//因装备改变而被毁掉的Activity它所存留下来的数据
Activity.NonConfigurationInstances lastNonConfigurationInstances;
}
它所存储的便是因装备改变而被毁掉的 Activity 它所存留下来的装备,只不过在这个办法傍边它的值仍是空的。
// 履行从头创立Activity
private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
PendingTransactionActions pendingActions, boolean startsNotResumed,
Configuration overrideConfig, String reason) {
//保留上次运用的Intent
final Intent customIntent = r.activity.mIntent;
//从头创立Acitivty之前需求把产生装备改变的Activity毁掉掉
if (!r.paused) {
performPauseActivity(r, false, reason, null /* pendingActions */);
}
if (!r.stopped) {
callActivityOnStop(r, true /* saveState */, reason);
}
// 毁掉Activity
handleDestroyActivity(r, false, configChanges, true, reason);
//创立和发动Activity
handleLaunchActivity(r, pendingActions, customIntent);
}
在从头创立 Acitivty 之前需求把产生装备改变的 Activity 毁掉掉,所以履行装备改变的 performPauseActivity()
办法以及 callActivityOnStop()
办法,在 callActivityOnStop()
同时履行 callActivityOnSaveInstanceState(r)
而且有时机存储数据。
@Override
public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
// 履行Activity毁掉办法的中心办法
performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
}
handleDestroyActivity()
办法里边有个 boolean getNonConfigInstance
参数, performDestroyActivity()
是履行 Activity 毁掉办法的中心办法:
// 毁掉Activity
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
activityClass = r.activity.getClass();
//
if (!r.stopped) {
callActivityOnStop(r, false /* saveState */, "destroy");
}
// 保存lastNonConfigurationInstances,然后保存了数据
if (getNonConfigInstance) {
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
}
}
假如 getNonConfigInstance == true
,则会履行 r.activity.retainNonConfigurationInstances()
办法,然后把 Activity 傍边受到装备改变而不想丢失的数据给保存起来,这样 ViewModelStore 目标也就被保存起来了。数据就被存储在 lastNonConfigurationInstances 里边:

这个数据都会被保存到 ActivityClientRecord 的 lastNonConfigurationInstances 里边,这个r目标是经过 ActivityClientRecord r = mActivities.get(tmp.token)
获取的,那实践上就跟在 handleLaunchActivity()
傍边获取到的那个 ActivityClientRecord 目标是同一个实例目标。
那么在 performDestroyActivity()
中的 ActivityClientRecord 就包含了被毁掉的 Activity 存留下来的目标,毁掉之后就履行 Avtivity 重建作业,重建最终会走到 performLaunchActivity()
办法,履行 newActivity()
去 New 一个 Activity,还会履行 activity.attach()
办法:
// 履行创立发动Activity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
//
Activity activity = null;
// 创立Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
//里边保存了lastNonConfigurationInstances,省掉部分参数
activity.attach(appContext, this, r.lastNonConfigurationInstances );
r.lastNonConfigurationInstances = null;
r.activity = activity;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
r.setState(ON_CREATE);
}
return activity;
}
这儿又把 r.lastNonConfigurationInstances
传递了进去,在 Activity 类中的 attach()
办法就把 lastNonConfigurationInstances
保存起来:
#Activity.java
final void attach(Context context, ActivityThread aThread,
NonConfigurationInstances lastNonConfigurationInstances ) {
// 保存lastNonConfigurationInstances
mLastNonConfigurationInstances = lastNonConfigurationInstances;
}
所以咱们在 CompontentActivity 傍边的 getLastNonConfigurationInstance()
中的 mLastNonConfigurationInstances 获取到数据了:
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
那么就能够在 getViewModelStore()
中获取到 NonConfigurationInstances 然后完结 viewModelStore 目标的复用。
@Override
public ViewModelStore getViewModelStore() {
// 假如存储器为空则从NonConfigurationInstances中获取
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
//从NonConfigurationInstances中恢复ViewModelStore
mViewModelStore = nc.viewModelStore;
}
// 假如还为空则创立一个ViewModelStore
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
也便是说,ActivityThread 中的 ActivityClientRecord 是不受 Activity 毁掉重建的影响而被保存下来,ActivityClientRecord中的lastNonConfigurationInstances也就被保存下来,那么ComponentActivity中的NonConfigurationInstances的viewModelStore就被保存下来完结复用。
到这儿 ViewModel 复用的剖析完了,本质上便是 ViewModelStore 的复用,顺便剖析了一把 Activity 毁掉重建的流程。
四、总结
ViewModel 的履行流程如下:

-
ViewModelProvider 从 ViewModelStore 依据 key 获取 ViewModel实例,判别该实例的 Class 类型的,假如是则直接回来,假如不是则会依据 mFactory 是什么类型的,来决定是用什么创立办法来创立 ViewModel 实例,创立完结后存储到 ViewModelStore 中。
-
Activity 完结了
ViewModelStoreOwner
这个接口,并复写了getViewModelStore()
办法,先从 NonConfigurationInstances 里边获取 ViewModelStore,假如没有就创立新的实例并保存起来。 -
ViewModelStore 经过 key-value 的办法存储 ViewModel,而它自己在 Activity 因装备改变而毁掉再重建时,调用
onRetainNonConfigurationInstance()
存储在 NonConfigurationInstances 里边。 -
Activity 毁掉时会将 NonConfigurationInstances 保存在
ActivityThread#ActivityClientRecord
中,重建后通Activity.attach()
从头传递给Activity,完结复用。 -
ActivityThread 中的 ActivityClientRecord 是不受 Activity 毁掉重建的影响而被保存下来,ActivityClientRecord 中的 lastNonConfigurationInstances 也就被保存下来,那么 ComponentActivity 中的 NonConfigurationInstances 的 ViewModelStore 就被保存下来完结复用。
由于 ViewModel 能够完结数据复用,本质上是 ViewModel 的实例目标得到了复用。
ViewModel 和 onSaveIntanceState 有什么区别:
- onSaveIntanceState 只能存储轻量级的 key-value 键值对数据,非装备改变导致的页面收回时才触发,此刻数据存储在 ActivityRecord 中。
- ViewModel 能够放恣意数据,因装备改变导致的页面被收回才有用,此刻存在 ActivityThread#ActivityClientRecord 中。
可是假如由于内存缺乏,电量缺乏等体系原因导致的页面被收回重建后 ViewModel 还能不能被复用呢?答案是能够的,下篇文章讲解。
一个大型的 Android 项目架构最佳实践,根据Jetpack组件 + MVVM架构模式
,加入 组件化
、模块化
、协程
、Flow
、短视频
。项目地址:github.com/suming77/Su…
点重视,不走失
好了各位,以上便是这篇文章的全部内容了,很感谢您阅读这篇文章。我是suming,感谢各位的支持和认可,您的点赞便是我创造的最大动力。山水有相逢,咱们下篇文章见!
自己水平有限,文章不免会有错误,请批评指正,不胜感激 !
参阅链接:
- ViewModel官网