1. SavedStateHandle简介
SavedStateHandle搭配ViewModel作为状态保存使用,ViewModel虽然也保存了状态,但仅限于屏幕旋转等资源配置变更导致Activity和Fragment销毁,如果是系统kill导致的销毁无法还原,SavedStateHandle就可以对ViewModel里的数据进行还原。
2. SavedStateHandle的简单使用
1. 依赖的引入
ext {
lifecycle_version = "2.4.1"
}
dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
}
2. ViewModel绑定SavedStateHandle
ViewModel:
class MyViewModel(private val savedStateHandle: SavedStateHandle): ViewModel()
AndroidViewModel:
class MyViewModel(private val application: Application, private val savedStateHandle: SavedStateHandle): AndroidViewModel(application)
带SavedStateHandle的ViewModel有专门的工厂类进行实现(SavedStateViewModelFactory),我们只需要把相应的构造参数按照以上方法进行书写即可,需要使用application就用AndroidViewModel。
3. SavedStateViewModelFactory
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner)
在工厂构造方法中,我们需要传入Activity和Fragment的LifecycleOwner, Application可传可不传,但如果在第二步中你用的AndroidViewModel就需要传入。
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
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);
}
// doesn't need SavedStateHandle
if (constructor == null) {
return mFactory.create(modelClass);
}
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
if (isAndroidViewModel && mApplication != null) {
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
viewmodel = constructor.newInstance(controller.getHandle());
}
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
return viewmodel;
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to access " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("An exception happened in constructor of "
+ modelClass, e.getCause());
}
}
在重写的create方法中通过isAndroidViewModel 和 mApplication != null来判断如何对ViewModel进行初始化,所以第二步需要固定构造参数。如果有特殊需求可以copy源码对工厂类进行重写。
4. 在Activity和Fragment中初始化
viewModel = ViewModelProvider(this, SavedStateViewModelFactory(application, this)).get(MyViewModel::class.java)
以上步骤就可以初始化一个带有SavedStateHandle的ViewModel了。
5. SavedStateHandle在ViewModel中的使用
SavedStateHandle可以缓存LiveData、也可缓存普通的数据;除了常用的List、String、Int等,其他实体需要接入Serializable或者注解@Parcelize实现序列化Parcelable,否则在应用销毁时缓存数据报错。
SavedStateHandle.getLiveData<String>("key")
SavedStateHandle.get<String?>("key")
缓存非序列化的类、实体,我们可以使用setSavedStateProvider方法返回Bundle实现。
savedStateHandle.setSavedStateProvider("key") {
if (file != null) {
file
} else {
Bundle()
}
}
以上就是SavedStateHandle的简单使用。