概览
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
疑问1 ViewModel怎么保留实例
疑问2 ViewModel什么时候执行onCleared清除方法
使用
先创建一个类继承ViewModel,如以下示例代码所示:
public class TempModel extends ViewModel {
public TempModel() {
Log.d("TempModel", "create " + getClass().getSimpleName());
}
@Override
protected void onCleared() {
super.onCleared();
Log.d("TempModel", "onCleared " + getClass().getSimpleName());
}
}
然后,您可以从 Activity 访问该对象,如下所示:
public class MainActivity extends AppCompatActivity {
private TempModel mTempModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTempModel = new ViewModelProvider(this).get(TempModel.class);
}
}
如果重新创建了该 Activity,它接收的 TempModel 实例与第一个 Activity 创建的实例相同。当所有者 Activity 完成时,框架会调用 ViewModel 对象的 onCleared() 方法,以便它可以清理资源。
注意:ViewModel 绝不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。
ViewModel怎么保留实例
ViewModel 对象存在的时间比Activity对象更长, 因为是通过onRetainNonConfigurationInstance的方式保留了实例,activity重启的时候不会销毁,而是待恢复新的对象activity时把ViewModel实例在导入给activity这个新实例。
这里我们主要看看是怎么实现的先看看ViewModelProvider 的构造
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
这里会传递两个参数给this,
第一个owner.getViewModelStore()
字面意思是通过owner获取一个ViewModel的商店或者是存储等。
第二个owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance()
字面意思是获取获取提供工厂,默认是HasDefaultViewModelProviderFactory这个类
先看 owner是什么?
public interface ViewModelStoreOwner {
/**
* Returns owned {@link ViewModelStore}
*
* @return a {@code ViewModelStore}
*/
@NonNull
ViewModelStore getViewModelStore();
}
从代码上看他是一个ViewModelStoreOwner的接口,在Activity的调用ViewModelProvider的时构造传的是this。 这说明我们activity 肯定实现了这个ViewModelStoreOwner,那么我们从当前Activity找起
public class MainActivity extends AppCompatActivity {
FragmentActivity
public class AppCompatActivity extends FragmentActivity implements AppCompatCallback,
TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider {
ComponentActivity
public class FragmentActivity extends ComponentActivity implements
ActivityCompat.OnRequestPermissionsResultCallback,
ActivityCompat.RequestPermissionsRequestCodeValidator {
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
在ComponentActivity类中找到ViewModelStoreOwner接口
那么在这个类中找到他的实现方法getViewModelStore
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
这个代码有点熟悉,当mViewModelStore等于空的时候会通过getLastNonConfigurationInstance这个方法获取nc的实例,在通过nc.viewModelStore; 赋值给mViewModelStore,如果nc为空则重现创建一个ViewModelStore
getLastNonConfigurationInstance这个方法是获取最后一次实例保留,可以里理解activity销毁时保留的实例传递给了当前新的Activity,与之成对的保留方法
@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;
}
onRetainNonConfigurationInstance这个方法是在销毁时保留的实例的方法。
具体可参考Activity的内部实例保存-onRetainNonConfigurationInstance
继续看ViewModelProvider的get方法
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
下面是get的重载方法
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//通过mViewModelStore获取ViewModel实例
ViewModel viewModel = mViewModelStore.get(key);
//第一次viewModel获取为空则不会走这个if里面
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
//默认都是KeyedFactory这个工厂类,里面就是通过class反射创建一个实例
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
//通过mViewModelStore保存ViewModel实例
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
ViewModel什么时候执行onCleared清除方法
这里了解完ViewModel为什么生命周期时间大于Activity,在看看他如何监听销毁的。这里就需要看
ComponentActivity的构造函数
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()) {
getViewModelStore().clear();
}
}
}
});
//省略...
}
先看 getViewModelStore().clear();
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
//省略...
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
ViewModelStore里面有个mMap 是包含当前activity所有的ViewModel对象。
在看看ViewModel 的clear
public abstract class ViewModel {
//省略...
protected void onCleared() {
}
@MainThread
final void clear() {
//省略...
onCleared();
}
//省略...
}
最终会调到onCleared ,故也会执行到我们自定义的TempModel类的onCleared方法
public class TempModel extends ViewModel {
public TempModel() {
Log.d("TempModel", "create " + getClass().getSimpleName());
}
@Override
protected void onCleared() {
super.onCleared();
Log.d("TempModel", "onCleared " + getClass().getSimpleName());
}
}
好,回到ComponentActivity构造里的注册监听, getLifecycle().addObserver
先看看getLifecycle()方法实现
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
查看定义,是一个LifecycleRegistry类
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
这里先不展开,后续单独一篇文章来探讨,这里直接给出结论:
LifecycleRegistry 是一个生命周期的注册类,addObserver方法是这个类的注册方法,主用用于监听Activity或者Fragment的生命周期。
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//这里是判断event 的事件是否是销毁
if (event == Lifecycle.Event.ON_DESTROY) {
//在判断是否是配置改动而销毁的
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});