前言
阅读本篇文章前最好先看上篇文章ViewModel源码阅读(一)ViewModel的生命周期
在阅读SavedStateHandle之前,我们需要搞清上篇文章通过getLastNonConfigurationInstance和onRetainNonConfigurationInstance存储的数据,与通过onSaveInstanceState和Bundle存储的数据有什么不同
我这里直接就说出结论了
getLastNonConfigurationInstance是通过NonConfigurationInstances保存状态的,这个状态可以获取的前提是进程没有被销毁
onSaveInstanceState中Bundle是通过Parcel保存状态的,这种保存的状态是非依附于进程的,当前进程被杀死,状态也是保留的
详细可以参考这篇文章,这里就不展开讨论了
在上面逻辑基础上,和上篇文章分析的ViewModel生命周期,我们可以推测出,ViewModel在进程被系统杀死时,再恢复时,是重新创建实例的,所以ViewModel引入了SavedStateHandle,来做轻量数据状态暂存
分析代码
这块的代码我第一次看的时候有点绕,因为关联类太多了,所以这块代码单独独立出来
下面开始阅读源码
@NonNull
@Override
public T create(@NonNull String key, @NonNull Class modelClass) {
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor constructor;
//获取构造函数,判断是否需要传入SavedStateHandle
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);
}
//核心方法,用来创建Handle的关键代码
//此处传入了一个mSavedStateRegistry 和mLifecycle 作用暂时未知
//key和mDefaultArgs分别对应ViewModel的唯一标识和getIntent中暂存的数据
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
//下面的代码就是传入handle的
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方法,我们继续研究create里是都创建了什么
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
//通过registry获取Bundle ,此处推测registry应该也是一个存储数据的封装类,此处代码应该是一个恢复获取状态的代码
Bundle restoredState = registry.consumeRestoredStateForKey(key);
//创建ViewModel中的Handle
SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//创建对外提供的controller
SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//下面这两段代码等将SavedStateRegistry研究明白再看
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
return controller;
}
上面的代码大体就是一个SavedStateHandleController创建过程,涉及到SavedStateRegistry,SavedStateHandleController两个类和controller.attachToLifecycle,tryToAddRecreator两个方法
先研究SavedStateRegistry
在SavedStateViewModelFactory发现SavedStateRegistry是SavedStateViewModelFactory构造函数在SavedStateRegistryOwner中获取的,SavedStateRegistryOwner是在CommponentActivity中实现的,主要是一个getSavedStateRegistry的实现
而getSavedStateRegistry方法设计到mSavedStateRegistryController变量。。。
mSavedStateRegistryController变量在类成员变量中初始化,代码如下
ComponentActivity
final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
SavedStateRegistryController的代码如下,
public final class SavedStateRegistryController {
private final SavedStateRegistryOwner mOwner;
private final SavedStateRegistry mRegistry;
//在构造函数传入一个Lifecycle的Owner
private SavedStateRegistryController(SavedStateRegistryOwner owner) {
mOwner = owner;
//这个玩意整体看了下,应该是真正零时缓存数据的操作类(google 你来解释下为啥要套的这么深?没有更好的方案了吗?)
mRegistry = new SavedStateRegistry();
}
//提供对外使用的操作存储类
@NonNull
public SavedStateRegistry getSavedStateRegistry() {
return mRegistry;
}
//这里是核心代码,一行一行注释,主要是数据使用前封装
//这里主要是将恢复后的数据拿到,而且通过lifecycle将获取时机控制在onCreate中
@MainThread
public void performRestore(@Nullable Bundle savedState) {
//此处拿到在ComponentActivity实例的SavedStateRegistryOwner
Lifecycle lifecycle = mOwner.getLifecycle();
//如果Lifecycle.State的状态在OnCreate之前会回调到这里,说明是有问题的,抛出异常
if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
throw new IllegalStateException("Restarter must be created only during "
+ "owner's initialization stage");
}
//这里做个一个一次性事件的添加,为啥是一次性?Recreator里面会解答
lifecycle.addObserver(new Recreator(mOwner));
//将savedState里的Bundle读出来,下面会分析
mRegistry.performRestore(lifecycle, savedState);
}
//数据保存前封装 outBundle就是onSaveInstanceState中的Bundle
@MainThread
public void performSave(@NonNull Bundle outBundle) {
mRegistry.performSave(outBundle);
}
//提供快捷创建函数
@NonNull
public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
return new SavedStateRegistryController(owner);
}
}
上面这段代码主要有三个工作内容
1,将ComponentActivity的lifeCycle拿到
2,在创建真正的读取保存类SavedStateRegistry
3,控制将恢复数据的时机控制在onCreate,并封装SavedStateRegistry
最后看SavedStateRegistry几个关键代码
//这里savedState 是ComponentActivity里onCreate中的savedInstanceState 通过mSavedStateRegistryController.performRestore传入
@MainThread
void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
if (mRestored) {
throw new IllegalStateException("SavedStateRegistry was already restored.");
}
//这里获取到恢复的savedState里面的数据在 performSave 中可以看到格式
if (savedState != null) {
//此处的mRestoredState在SavedStateHandleController中的 registry.consumeRestoredStateForKey会用到
mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
}
//做了一个监听,如果执行了Lifecycle.Event.ON_STOP 的话,记录mAllowingSavingState,用来判断是否是正常流程
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;
}
这里是当onSaveInstanceState执行时,执行的代码
@MainThread
void performSave(@NonNull Bundle outBundle) {
//将内存中的数据全部装进来
Bundle components = new Bundle();
if (mRestoredState != null) {
components.putAll(mRestoredState);
}
//遍历各个生成的handle,保存handle中的数据,后面看handler源码就会发现每个handle都会保存一个SavedStateProvider
for (Iterator> it =
mComponents.iteratorWithAdditions(); it.hasNext(); ) {
Map.Entry entry1 = it.next();
components.putBundle(entry1.getKey(), entry1.getValue().saveState());
}
outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}
上面代码主要做了一个数据读取和保存,和我们平时写普通的数据零时保存一样,只是做了封装,mRestoredState作为存储和读取的所有数据的全局变量
最后看下ComponentActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//代码不多,没做代码省略,这句话执行后,相当于就是从恢复中拿到了数据
mSavedStateRegistryController.performRestore(savedInstanceState);
mContextAwareHelper.dispatchOnContextAvailable(this);
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
Lifecycle lifecycle = getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
}
super.onSaveInstanceState(outState);
//这句话执行后,将数据零时存储在恢复区
mSavedStateRegistryController.performSave(outState);
}
所以通过以上代码的阅读,我们已经发现,SavedStateHandle的核心逻辑就是通过onSaveInstanceState做临时存储,数据恢复只是封装了两层,做了很多逻辑判断
SavedStateRegistryController->SavedStateRegistry->执行恢复存储。
再回到SavedStateHandleController
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
//这行代码,下面会简单看下,主要是为了去哪在系统恢复Activity时,通过getIntent中的内容
Bundle restoredState = registry.consumeRestoredStateForKey(key);
//这里创建Handle核心代码
SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//创建controller 主要是绑定registry数据和handle中mSavedStateProvider的关系
SavedStateHandleController controller = new SavedStateHandleController(key, handle);
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
return controller;
}
先简单看下consumeRestoredStateForKey中的东西
@MainThread
@Nullable
public Bundle consumeRestoredStateForKey(@NonNull String key) {
if (!mRestored) {
throw new IllegalStateException("You can consumeRestoredStateForKey "
+ "only after super.onCreate of corresponding component");
}
if (mRestoredState != null) {
Bundle result = mRestoredState.getBundle(key);
mRestoredState.remove(key);
if (mRestoredState.isEmpty()) {
mRestoredState = null;
}
return result;
}
return null;
}
代码很简单,主要是通过ViewModel唯一关键字获取mRestoredState里存储的Bundle,而这个mRestoredState我们前面代码已经知道就是用来做activity销毁前存储和activtiy恢复时读取的Bundle,所以这里相当于通过Viewmodle的Key获取在ViewModel中临时存储的数据
再看createHandle的代码
static SavedStateHandle createHandle(@Nullable Bundle restoredState,
@Nullable Bundle defaultState) {
//如果没有需要缓存或者恢复的数据,直接创建SavedStateHandle
if (restoredState == null && defaultState == null) {
return new SavedStateHandle();
}
Map state = new HashMap<>();
if (defaultState != null) {
for (String key : defaultState.keySet()) {
state.put(key, defaultState.get(key));
}
}
//如果有需要缓存的数据创建且没有恢复数据的情况,一个带缓存数据的SavedStateHandle
if (restoredState == null) {
return new SavedStateHandle(state);
}
ArrayList keys = restoredState.getParcelableArrayList(KEYS);
ArrayList values = restoredState.getParcelableArrayList(VALUES);
if (keys == null || values == null || keys.size() != values.size()) {
throw new IllegalStateException("Invalid bundle passed as restored state");
}
for (int i = 0; i < keys.size(); i++) {
state.put((String) keys.get(i), values.get(i));
}
//如果两个都有,那就两个都塞进去
return new SavedStateHandle(state);
}
这里需要看下handle把数据存到哪里了,在构造函数中
/**
* Creates a handle with the given initial arguments.
*/
public SavedStateHandle(@NonNull Map initialState) {
mRegular = new HashMap<>(initialState);
}
/**
* Creates a handle with the empty state.
*/
public SavedStateHandle() {
mRegular = new HashMap<>();
}
我们发现刚刚的数据全部塞到mRegular中了
这个mRegular就是一个Map,并且提供给外部使用
/**
* Returns a value associated with the given key.
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
@MainThread
@Nullable
public T get(@NonNull String key) {
return (T) mRegular.get(key);
}
/**
* Associate the given value with the key. The value must have a type that could be stored in
* {@link android.os.Bundle}
*
* @param any type that can be accepted by Bundle.
*/
@MainThread
public void set(@NonNull String key, @Nullable T value) {
validateValue(value);
@SuppressWarnings("unchecked")
MutableLiveData mutableLiveData = (MutableLiveData) mLiveDatas.get(key);
if (mutableLiveData != null) {
// it will set value;
mutableLiveData.setValue(value);
} else {
mRegular.put(key, value);
}
}
也就是说handle主要是提供了一个mRegular的Map提供业务层读取和存储(甚至提供了一个LiveData,这里就不展开了),但是真实存储的时候,我们发现是下面这段代码(上面已经阅读过,需要重新看下)
@MainThread
void performSave(@NonNull Bundle outBundle) {
...
for (Iterator> it =
mComponents.iteratorWithAdditions(); it.hasNext(); ) {
Map.Entry entry1 = it.next();
components.putBundle(entry1.getKey(), entry1.getValue().saveState());
}
outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}
这里发现是遍历的mComponents中的SavedStateProvider,执行的saveState方法,在Handle中也存在这样一段代码
private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() {
@SuppressWarnings("unchecked")
@NonNull
@Override
public Bundle saveState() {
// Get the saved state from each SavedStateProvider registered with this
// SavedStateHandle, iterating through a copy to avoid re-entrance
Map map = new HashMap<>(mSavedStateProviders);
for (Map.Entry entry : map.entrySet()) {
Bundle savedState = entry.getValue().saveState();
set(entry.getKey(), savedState);
}
// Convert the Map of current values into a Bundle
Set keySet = mRegular.keySet();
ArrayList keys = new ArrayList(keySet.size());
ArrayList value = new ArrayList(keys.size());
for (String key : keySet) {
keys.add(key);
value.add(mRegular.get(key));
}
Bundle res = new Bundle();
// "parcelable" arraylists - lol
res.putParcelableArrayList("keys", keys);
res.putParcelableArrayList("values", value);
return res;
}
};
上面的代码没有写注释,大体意思就是把mRegular中的数据塞到Bundle里,我们可以联想,应该是在performSave时,调用handle中的SavedStateProvider里的saveState方法获取Bundle并保存的,那就是handle中的SavedStateProvider会存到SavedStateRegistry的mComponents中。。但是在哪塞入的呢?我们再回到SavedStateHandleController中看下一个方法
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
Bundle restoredState = registry.consumeRestoredStateForKey(key);
SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//目前只有下面这两句可能会将handle里的SavedStateProvider和SavedStateRegistry里的mComponents做数据绑定了
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
return controller;
}
先看attachToLifecycle
void attachToLifecycle(SavedStateRegistry registry, Lifecycle lifecycle) {
if (mIsAttached) {
throw new IllegalStateException("Already attached to lifecycleOwner");
}
mIsAttached = true;
lifecycle.addObserver(this);
//这句话明显感觉就是用来绑定数据的
registry.registerSavedStateProvider(mKey, mHandle.savedStateProvider());
}
再看registerSavedStateProvider
@MainThread
public void registerSavedStateProvider(@NonNull String key,
@NonNull SavedStateProvider provider) {
//这里果然做了数据put
SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
if (previous != null) {
throw new IllegalArgumentException("SavedStateProvider with the given key is"
+ " already registered");
}
}
SafeIterableMap mComponents
public V putIfAbsent(@NonNull K key, @NonNull V v) {
Entry entry = get(key);
if (entry != null) {
return entry.mValue;
}
put(key, v);
return null;
}
看过最后这块代码,我们整个Handle的逻辑就很清晰了,下面说下文字流程
1在通过SavedStateViewModelFactory创建ViewModel时,先通过构造函数入参判断是否存在SavedStateHandle入参,如果存在就执行创建SavedStateHandleController
2通过SavedStateHandleController.create创建SavedStateHandleController,在创建SavedStateHandleController时将Activtiy中实现的SavedStateRegistryOwner通过getSavedStateRegistry传入mSavedStateRegistry
3mSavedStateRegistry在ComponentActivity通过SavedStateRegistryController.create()实例,并且在ComponentActivity中onCreate里执行了performRestore方法,在onSaveInstanceState里执行了performSave方法
4在SavedStateHandleController创建时,先获取mSavedStateRegistry在ComponentActivity里的onCreate是获取到的数据,并且将数据塞到创建的SavedStateHandle中的mRegular里
5再将SavedStateHandle封装到 SavedStateHandleController中,并将handel里的mSavedStateProvider塞到mSavedStateRegistry中的mComponents中
6当Activity被系统杀死时,执行onSaveInstanceState,触发mSavedStateRegistry.performSave
7在performSave时,遍历mComponents,执行mSavedStateProvider的saveState封装数据,塞到onSaveInstanceState的Bundle里
最后上自己画的handle代码简易逻辑图