【安卓开发系列 -- APP】JetPack -- SavedState
【1】SavedState 概念
SavedState 是为了弥补 ViewModel 无法直接感知 onSaveInstanceState 被触发的时机的缺陷而产生的;
在页面即将被销毁的时候,每个使用 SavedState 的 ViewModel 都会创建一个 Bundle 来存储自己的这份数据,最后这些 Bundle 会被汇总到一个 Bundle 中,然后再保存到 onSaveInstanceState(Bundle outState) 的 outState 中;
当页面恢复的时候,会从 onCreate(Bundle savedInstanceState) 中的 savedInstanceState 中取出原来存放的总的那个 Bundle,然后再取出一个个的属于 ViewModel 的子 Bundle,从而实现在 ViewModel 中复用之前存储的数据;
其实就是利用 Bundle 可以保存另一个 Bundle 这么一个特点,分层分区保存数据,让数据之间相互分离,进而方便整存整取;
【2】SavedState 使用示例 -- ViewModel 搭配 SavedState 实现数据复用
核心思想
当 Activity 的 onSaveInstanceState 方法被执行的时候,会触发 SavedStateHandle 的 Bundle saveState() 方法,从而保存其数据;当 Activity 被恢复的时候,在新建 ViewModel 实例对象的时候,会从 Activity 的 savedInstanceState 中提取之前存储数据,然后构造 SavedStateHandle 对象并把恢复的数据赋值给该对象,随后把 SavedStateHandle 传递到 ViewModel 中,从而复用其数据;
class SavedStateViewModel extends ViewModel {
// 需要引用 SavedStateHandle
private SavedStateHandle mHandle;
public SavedStateViewModel(SavedStateHandle handle) {
mHandle = handle;
// 实现数据的恢复
Object text = mHandle.get("text");
if (null == text) {
String time = String.valueOf(System.currentTimeMillis() / 1000);
// 实现数据的保存
mHandle.set("text", time);
QrLog.e("SavedStateViewModel 初始化数据 = " + time);
} else {
QrLog.e("SavedStateViewModel 恢复数据 = " + text);
}
}
}
// ViewModelActivity.java
class ViewModelActivity extends AppCompatActivity {
SavedStateViewModel mSavedStateViewModel;
void onCreate(Bundle savedInstanceState) {
// 这边创建时传入了 SavedStateViewModelFactory
mSavedStateViewModel = ViewModelProviders
.of(this, new SavedStateViewModelFactory(getApplication(), this))
.get(SavedStateViewModel.class);
QrLog.e("mSavedStateViewModel hashCode = " + mSavedStateViewModel.hashCode());
}
}
【3】SavedState 相关源码分析
SavedState 涉及的类结构图及其中的组成成员
**SavedStateRegistryOwner:**接口,用于获取 SavedStatedRegistry 对象;
SavedStateRegistryController:用于创建 SavedStatedRegistry,用于连接 Activity\Fragment 和 SavedStatedRegistry;
SavedStatedRegistry:数据存储、恢复中心;
SavedStateHandleController:用于从数据中心提出数据并创建 SavedStateHandle;
SavedStateHandle:单个 ViewModel 用于数据存储和恢复的对象;
SavedStateRegistry 模型图示
一个总 Bundle ,以 key-value 形式存储着每个 ViewModel 对应的子 Bundle;
SavedState 数据存储流程
逐一调用每个 SavedStateHandle 保存自己的数据,汇总成一个总的 Bundle,再存储到 Activity 的 savedState 对象中;
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
// public class LifecycleRegistry extends Lifecycle
// 绑定了生命周期
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
private final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
// 页面失去焦点时被系统调用
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
Lifecycle lifecycle = getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
// 更新 Lifecycle 的状态信息
((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
}
// 调用父类的 onSaveInstanceState
super.onSaveInstanceState(outState);
// 调用 performSave 转发给 SavedStateRegistryController
// outState 为 Activity 层面的 Bundle 实例
mSavedStateRegistryController.performSave(outState);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
}
public final class SavedStateRegistryController {
private final SavedStateRegistry mRegistry;
@MainThread
public void performSave(@NonNull Bundle outBundle) {
// 直接转发给 SavedStateRegistry
mRegistry.performSave(outBundle);
}
// 创建一个 SavedStateRegistryController 实例
@NonNull
public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
return new SavedStateRegistryController(owner);
}
}
public final class SavedStateRegistry {
// 用于保存 SavedStateProvider 实例
private SafeIterableMap<String, SavedStateProvider> mComponents =
new SafeIterableMap<>();
// 总的 Bundle 对象
// 当前 SavedStateRegistry 保存的数据
private Bundle mRestoredState;
@MainThread
void performSave(@NonNull Bundle outBundle) {
// 新建一个 Bundle 对象
Bundle components = new Bundle();
if (mRestoredState != null) {
// 若 mRestoredState 存在则将新建的 components 存入其中
/**
* Inserts all mappings from the given Bundle into this Bundle.
*/
components.putAll(mRestoredState);
}
// 遍历所有注册的 SavedStateProvider 的 saveState() 方法保存各自的数据
for (Iterator<Map.Entry<String, SavedStateProvider>> it =
mComponents.iteratorWithAdditions(); it.hasNext(); ) {
Map.Entry<String, SavedStateProvider> entry1 = it.next();
/**
* Inserts a Bundle value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*/
// 将每个 SavedStateHandle 返回的 bundle 汇总到 components 中
components.putBundle(entry1.getKey(), entry1.getValue().saveState());
}
/**
* Inserts a Bundle value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*/
// 将 components 存储到 outBundle 中
outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}
}
SavedStateHandle 参数传递到 ViewModel 的流程 -- SavedState 数据复用流程
提取出存储的 Bundle 数据对象流程
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
private final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 页面新建时派发给 SavedStateRegistryController
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
}
public final class SavedStateRegistryController {
private final SavedStateRegistryOwner mOwner;
private final SavedStateRegistry mRegistry;
private SavedStateRegistryController(SavedStateRegistryOwner owner) {
mOwner = owner; // mOwner 的值在 create 方法中由调用对象传入
mRegistry = new SavedStateRegistry();
}
@MainThread
public void performRestore(@Nullable Bundle savedState) {
// 获取 Lifecycle 实例
Lifecycle lifecycle = mOwner.getLifecycle();
// 判断 Lifecycle 实例的状态是否正确
if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
throw new IllegalStateException("Restarter must be created only during "
+ "owner's initialization stage");
}
// 建立生命周期观察者
// Recreator 实现了 GenericLifecycleObserver(扩展了 LifecycleEventObserver) 接口
// Recreator 提供了内部静态 final 类 SavedStateProvider 用于提供 SsavedStateHandle
lifecycle.addObserver(new Recreator(mOwner));
// 转发给 SavedStateRegistry 处理
mRegistry.performRestore(lifecycle, savedState);
}
// 创建一个 SavedStateRegistryController 实例
@NonNull
public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
return new SavedStateRegistryController(owner);
}
}
public final class SavedStateRegistry {
// 用于标记保存的状态是否已经恢复
private boolean mRestored;
// 用于标记是否允许进行数据存储操作
boolean mAllowingSavingState = true;
@MainThread
void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
// 确保保存状态的恢复只能进行一次
if (mRestored) {
throw new IllegalStateException("SavedStateRegistry was already restored.");
}
if (savedState != null) {
// 获取当前页面存储数据的 bundle 集合
mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
}
// 为 Lifecycle 实例添加新的观察者
lifecycle.addObserver(new GenericLifecycleObserver() {
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_START) {
mAllowingSavingState = true;
} else if (event == Lifecycle.Event.ON_STOP) {
mAllowingSavingState = false;
}
}
});
mRestored = true;
}
}
Bundle 数据对象的复用流程
创建 ViewModel 实例时,会从 SavedStateRegistry 获取当前 ViewModel 之前存储的数据并赋值给 SavedStateHandle 对象,并将 savedSateHandle 以参数的形式传递到 ViewModel 完成复用;
public class ViewModelProvider {
// 这里会判断 Activity/Fragment 是不是 HasDefaultViewModelProviderFactory 类型
// 若 Activity/Fragment 都实现了 HasDefaultViewModelProviderFactory 接口,
// 则当调用这个构造函数创建 ViewModelProvider 获取 ViewModel 的时候
// 都是由 SavedStateViewModelFactory 负责具体的创建以及参数传递的
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
}
public interface HasDefaultViewModelProviderFactory {
// 提供方法用于获取默认的 ViewModelProviderFactory 实例
@NonNull
ViewModelProvider.Factory getDefaultViewModelProviderFactory();
}
// ComponentActivity 实现了 HasDefaultViewModelProviderFactory 接口
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
private ViewModelProvider.Factory mDefaultFactory;
// 覆写了 HasDefaultViewModelProviderFactory 接口的 getDefaultViewModelProviderFactory 方法
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
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 (mDefaultFactory == null) {
// 此处新建了 SavedStateViewModelFactory 实例并返回
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
}
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
private final Bundle mDefaultArgs;
private final Lifecycle mLifecycle;
private final SavedStateRegistry mSavedStateRegistry;
private final ViewModelProvider.AndroidViewModelFactory mFactory;
// SavedStateViewModelFactory 创建 ViewMdodel 实例的方法
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
// 1. 判断 viewmodel 是不是 AndroidViewModel 的子类
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor<T> constructor;
if (isAndroidViewModel) {
// 2. 如果是 AndroidViewModel 的子类,
// 则尝试查找其是否拥有(Application, SavedStateHandle)两个参数的构造函数
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
// 3. 如果不是 AndroidViewModel 的子类,
// 则查找其是否拥有(SavedStateHandle)一个参数的构造函数
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
// doesn't need SavedStateHandle
if (constructor == null) {
// 4. 若上面两种方式都没找到相应的构造函数,则说明该 viewmodel 没有声明以上两种类型
// 此时使用 AndroidViewModelFactory 创建 viewmodel 实例
return mFactory.create(modelClass);
}
// 5. 执行到此处,则说明构造函数上存在 savedSateHandle 参数
// 这里会首先构建出 SavedStateHandleController 对象
// SavedStateHandleController 类的作用是从 SavedStateRegistry
// 提取出该 ViewModel 的 Bundle 数据对象,从而创建 savedSateHandle 对象
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
// 反射创建 ViewModel 对象并传递 SavedStateHandle 对象
if (isAndroidViewModel) {
// 带参数的反射构造 ViewModel 实例对象
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
// 没有参数的反射构造 ViewModel 实例对象
viewmodel = constructor.newInstance(controller.getHandle());
}
/**
* Sets a tag associated with this viewmodel and a key
*/
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
// 返回新创建的 ViewModel 实例对象
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());
}
}
}
final class SavedStateHandleController implements LifecycleEventObserver {
private final SavedStateHandle mHandle;
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
// 从数据中心 SavedStateRegistry 提出该 ViewModel 的 Bundle 数据对象
Bundle restoredState = registry.consumeRestoredStateForKey(key);
// 构建 SavedStateHandle 对象,并把 restoredState 中的数据再拆分出来,存储到 mRegular 这个 map 集合中
SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
// 新建 SavedStateHandleController 实例
SavedStateHandleController controller = new SavedStateHandleController(key, handle);
// 将 SavedStateHandleController 实例与宿主的生命周期关联
controller.attachToLifecycle(registry, lifecycle);
// 添加重新创建器
tryToAddRecreator(registry, lifecycle);
return controller;
}
SavedStateHandle getHandle() {
return mHandle;
}
}
附录
Android 生命周期各个方法之间的调用关系图
参考
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【1】跟架构师学Jetpack
【2】Android-Jetpack笔记-ViewModelSavedState