ViewModel 为什么被设计出来,解决了什么问题
1.不会因为屏幕旋转而销毁,减少了维护状态的工作。
2.由于在作用域内单一实例的特性,使得多个fragment之间可以方便通信,并且维护同一个数据状态。
3.完善了MVVM架构,使得解耦更加纯粹。
ViewModel的销毁
activity的销毁:
public ComponentActivity() {
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
// 销毁ViewModel
getViewModelStore().clear();
}
}
}
});
}
最终在调用了ViewModelStore类中的clear()方法:
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
ViewModelScope是什么?
viewModelScope 是一个 ViewModel 的 Kotlin 扩展属性。它能在ViewModel销毁时 (onCleared() 方法调用时) 退出。所以只要使用了 ViewModel,就可以使用 viewModelScope在 ViewModel 中启动各种协程,而不用担心任务泄漏。
ViewModel 是否涉及序列化与反序列化?
是不涉及的,数据不涉及跨进程通信,都是直接在当前应用进程的内存中传递。
一个 Activity 中是否支持多个 ViewModel ?
准确的说,是支持多个 key 不一致的 ViewModel 对象,因为 ViewModelStore 的本质是一个维护 Key-ViewModel 的
map 容器。
Activity横竖屏切换时为什么viewModel能保存持有的数据
在Activity实例中重写onRetainCustomNonConfigurationInstance、getLastNonConfigurationInstance方法,打印数据,当横竖屏旋转屏幕时,会打印这两个方法,一个是activity销毁时调用,一个是activity重建时调用,这两个方法是ComponentActivity透给activity可以自己实现的方法,用于给子类保存临时数据用的。
override fun onRetainCustomNonConfigurationInstance(): Any? {
Log.i("minfo", "onRetainCustomNonConfigurationInstance")
return super.onRetainCustomNonConfigurationInstance()
}
override fun getLastNonConfigurationInstance(): Any? {
Log.i("minfo", "getLastNonConfigurationInstance")
return super.getLastNonConfigurationInstance()
}
进入ComponentActivity类的方法:
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
@Override
@Nullable
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
public Object onRetainCustomNonConfigurationInstance() {
return null;
}
横竖屏切换调用onRetainNonConfigurationInstance,获取了页面的mViewModelStore,将mViewModelStore保存到NonConfigurationInstances的实例中。
Activity类中方法:
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
横竖屏切换恢复时调用getLastNonConfigurationInstance,获取activity中的mLastNonConfigurationInstances实例,获取其中的viewmodelStore,赋值给activity的viewmodelstore。
为什么横竖品切换明明调用了activity的onDestroy,viewmodel却没有调用clear呢?
如果是手动销毁页面,会走viewmodel的clear方法清除数据。但是如下代码进行了判断,当activity调用destroy,如果是因为横竖屏切换,这里就不会让viewModel清除数据。
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
参考:
https://blog.csdn.net/OneDeveloper/article/details/115049760
https://blog.csdn.net/chuhe1989/article/details/109805408
网友评论