1 前言
谷歌I/O 发布了一系列辅助android开发者的实用工具,合称Jetpack,其通过提供现代化应用架构以及提供强健的向后兼容能力等方式,让开发者能够快速、轻松地创造拥有卓越性能的高质量应用。本系列文章会介绍一下5个方面:
本文介绍LiveData、ViewModel以及SaveState框架,主要涉及以下三方引用:
-
lifecycle-livedata:2.2.0、lifecycle-livedata-core:2.3.0
主要类LiveData、ComputableLiveData;利用观察者模式达到数据驱动的效果,监听者利用lifecycle架构可以感知生命周期
-
savedstate:1.1.0
提供了activity/fragment中横竖屏切换以及异常销毁时数据保存机制
-
lifecycle-viewmodel:2.3.0、lifecycle-viewmodel-savedstate:2.3.0
提供了vm角色基础模型,并提供vm数据在横竖屏切换以及异常销毁时保存机制
2 LiveData库
LiveData架构存在与两个库,其中类图如下
- LiveData:抽象类,livedata的核心类,实现了数据的改变与获取以及数据变化监听
- MutableLiveData:LiveData的实现类
- ComputableLiveData:抽象类, LiveData装饰类,内部内聚数据变化功能
- Observer:接口,数据变化监听者
- MediatorLiveData:LiveData实现类,也是livedata以及其监听对象的管理者管理者
这里主要介绍LiveData、ComputableLiveData、MediatorLiveData类
2.1 LiveData抽象类
内容主要涉及数据改变、监听存储、事件分发
2.1.1 监听存储
监听的注册和解绑根据是否有生命周期感知能力而有所不同
生命周期感知
注册
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
具有生命周期感知时,监听者被装饰为LifecycleBoundObserver对象并保存起来,并且注册到生命周期中;LifecycleOwner为具有生命周期的对象
解绑
public void removeObservers(@NonNull final LifecycleOwner owner) {
assertMainThread("removeObservers");
for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
if (entry.getValue().isAttachedTo(owner)) {
removeObserver(entry.getKey());
}
}
}
通过判断是否对生命周期进行绑定,进而通过removeObserver(@NonNull final Observer<? super T> observer)来移除每一个监听者
无生命周期感知
注册
public void observeForever(@NonNull Observer<? super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
监听者装饰为AlwaysActiveObserver对象,并存储
解绑
public void removeObserver(@NonNull final Observer<? super T> observer) {
assertMainThread("removeObserver");
ObserverWrapper removed = mObservers.remove(observer);
if (removed == null) {
return;
}
removed.detachObserver();
removed.activeStateChanged(false);
}
移除监听者,并进行取消生命周期监听(无感知则无处理),并改变活跃个数
2.1.2 数据变化
两个函数提供了数据变化提交调用postValue、setValue;postValue方法为异步提交,最后也是通过setValue来达到效果的;
postValue方法
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
数据变化采用了锁机制,达到异步安全;首先修改中间数据对象,并提交到主线程进行更新;mPendingData为NOT_SET时说明数据未发生变化,不为NOT_SET,说数据正在发生变化还未结束
任务对象
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
采用锁机制,获取数据最新内容;并通过setValue方法进行设置;和异步提交采用同一锁进行同步,并采用中间变量标志状态,减少锁持有时常,并保证异步提交数据后,主线程确定数据变化后不会在更新过程中数据变动
setValue方法
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
记录版本、改变数据,并通过dispatchingValue进行数据变化分发;
2.1.3 分发
活跃状态分发、以及数据值分发
活跃状态
void changeActiveCounter(int change) {
int previousActiveCount = mActiveCount;
mActiveCount += change;
if (mChangingActiveState) {
return;
}
mChangingActiveState = true;
try {
while (previousActiveCount != mActiveCount) {
boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
previousActiveCount = mActiveCount;
if (needToCallActive) {
onActive();
} else if (needToCallInactive) {
onInactive();
}
}
} finally {
mChangingActiveState = false;
}
}
活跃状态处理存在与监听注册、解绑或者生命周期感知销毁时,进行处理
- onActive()调用出现在从没有活跃的监听者到出现活跃监听者
- onInactive()调用出现在从有活跃的监听到没有活跃的监听者
- 这里预防了嵌套调用,采用活跃数量、以及是否正在处理来解决;处理状态决定后面流程只执行一次,循环判断当前活跃监听数量与之前活跃数量不同,来标志处理流程中是否又发生了变化,进而达到数据处理符合最终结果
数据分发
处理存在与监听注册、生命周期状态变化、数据改变;其中生命周期变化,只会从不活跃到活跃才会发生;而监听注册只在注册时处于活跃状态才会分发
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
而具体分发时依据传参不同来表明场景不同,参数为空,表示数据发生变化,通知所有监听者;不为空只通知当前监听者;但是这里面也存在嵌套场景;采用下面两个变量进行处理
- mDispatchingValue表明是否在正在进行分发
- mDispatchInvalidated表明分发过程状态是否再次变化
- 若单独分发到某个监听者时存在嵌套,置空参数,来处理数据分发者漏掉的情况
- 分发所有监听者,发生嵌套时,终止当前迭代,重新迭代,减少无效分发或者漏掉分发对象
considerNotify方法进行对每个监听者分发,通过状态的活跃状态、数值版本,来避免不必要的分发;
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
2.2 ComputableLiveData类
内部包含了LiveData实现类;抽象方法compute,进行数据计算;外部只需监听即可;触发计算时机有两个,调用invalidate方法、或者Livedata的onActivie方法触发(更具体场景见livedata类分析);
数据监听触发计算
public ComputableLiveData() {
this(ArchTaskExecutor.getIOThreadExecutor());
}
public ComputableLiveData(@NonNull Executor executor) {
mExecutor = executor;
mLiveData = new LiveData<T>() {
@Override
protected void onActive() {
mExecutor.execute(mRefreshRunnable);
}
};
}
构造器方法,默认数据执行在Arch的IO线程池中,LiveData实现对象,在onActive中执行mRefreshRunnable任务
invalidate方法触发计算
在主线程中执行mInvalidationRunnable任务
final Runnable mInvalidationRunnable = new Runnable() {
@MainThread
@Override
public void run() {
boolean isActive = mLiveData.hasActiveObservers();
if (mInvalid.compareAndSet(false, true)) {
if (isActive) {
mExecutor.execute(mRefreshRunnable);
}
}
}
};
public void invalidate() {
ArchTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
}
如果存在活跃用户,且当前处在未进行刷新状态,则异步执行计算任务
计算任务
final Runnable mRefreshRunnable = new Runnable() {
@WorkerThread
@Override
public void run() {
boolean computed;
do {
computed = false;
if (mComputing.compareAndSet(false, true)) {
try {
T value = null;
while (mInvalid.compareAndSet(true, false)) {
computed = true;
value = compute();
}
if (computed) {
mLiveData.postValue(value);
}
} finally {
mComputing.set(false);
}
}
} while (computed && mInvalid.get());
}
};
compute方法可以不考虑异常,但异常时,不进行分发;其中仍然考虑了嵌套场景,也考虑并发场景;采用原子类+循环来解决并发;通过刷新状态、当前计算状态以及线程计算状态来进行循环处理
- mComputing:boolean原子类,原子值为false,表明计算结束或者未计算
- computed临时变量,用于表示本次调用的上次计算是否完毕
- mInvalid:boolean原子类,用来表示是否已经刷新过了,原子值为true时表明需要刷新
这里的循环很有意思,一般来讲有计算状态和刷新状态,就可以搞定,为啥还有增加个临时变量且最外层要判断invalid状态呢?
这里是接收到刷新状态,在当前线程中执行,而不必等待下个刷新任务去执行;下个任务有可能被阻塞了,减少了不及时传递的可能
2.3 MediatorLiveData类
内部实现并不复杂,这里不进行具体介绍了;这里说下其特性
- 本身实现了LiveData
- 统一管理一系列LiveData以及其监听者;这些LiveData又具有以下特性
- 这些管理的livedata的监听者不具备生命周期感知
- livedata的监听者有且仅有一个
- 这些监听者是否监听取决与当前类自己的数据活跃监听者数量
- 当前类在onActive、onInactive、监听、解绑方法中管理其存储的livedata相关的监听者的注册解绑
有这些特性可以知道,使用的场景很有意思,在Work库中被使用了;简化来说这种场景就是:一个数据被监听处理,则其它一些列的监听状态也需要跟着处理(有点流水线,机器运转工人需要干活,机器停止工人就不要干活的场景)
3 savestate库
类图如下
- SavedStateRegistryOwner:state存储和恢复的宿主,这里主要是activity、fragment、
- SavedStateRegistryController:宿主对state存储和恢复的枢纽
- SavedStateRegistry:存储和恢复数据的主要管理者
- SavedStateRegistry.SavedStateProvider: 状态数据的具体提供者
- SavedStateRegistry.AutoRecreated:生命周期中根据状态自动执行类
- Recreator.SavedStateProvider:静态内部类,包权限;提供SavedStateRegistry.AutoRecreated的class的存储;暂时所知其内部只有存储SavedStateHandleController.OnRecreation类
- Recreator:SavedStateRegistry.AutoRecreated的class数据获取,并自动执行以及初始化
下面主要介绍SavedStateRegistryController、SavedStateRegistry、Recreator和其内部类
3.1 SavedStateRegistryController类
逻辑实现主要为存储和取出;
取出
public void performRestore(@Nullable Bundle savedState) {
Lifecycle lifecycle = mOwner.getLifecycle();
if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
throw new IllegalStateException("Restarter must be created only during "
+ "owner's initialization stage");
}
lifecycle.addObserver(new Recreator(mOwner));
mRegistry.performRestore(lifecycle, savedState);
}
当前状态为Lifecycle.State.INITIALIZED,下个状态为Lifecycle.Event.ON_CREATE;也即activity 的onCreate、fragment的performCreate方法中调用;调用SavedStateRegistry来完成存储数据解析;Recreator中完成SavedStateRegistry.AutoRecreated的对象创建以及初始化(其实是完成了viewmodel的数据解析和设置,以便viewmodel创建时自动数据填充)
存储
@MainThread
public void performSave(@NonNull Bundle outBundle) {
mRegistry.performSave(outBundle);
}
在activity的onSaveInstanceState,fragment的performSaveInstanceState方法中执行,也即在ON_STOP之前ON_PAUSE之后
3.2 SavedStateRegistry类
其中包括SavedStateProvider管理,数据管理,AutoRecreated对象的存储
3.2.1 SavedStateProvider管理
public void registerSavedStateProvider(@NonNull String key,
@NonNull SavedStateProvider provider) {
SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
if (previous != null) {
throw new IllegalArgumentException("SavedStateProvider with the given key is"
+ " already registered");
}
}
public void unregisterSavedStateProvider(@NonNull String key) {
mComponents.remove(key);
}
通过集合SafeIterableMap<String, SavedStateProvider>存储以获取来达到SavedStateProvider的记录
3.2.2 AutoRecreated对象存储
public void runOnNextRecreation(@NonNull Class<? extends AutoRecreated> clazz) {
if (!mAllowingSavingState) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mRecreatorProvider == null) {
mRecreatorProvider = new Recreator.SavedStateProvider(this);
}
try {
clazz.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Class" + clazz.getSimpleName() + " must have "
+ "default constructor in order to be automatically recreated", e);
}
mRecreatorProvider.add(clazz.getName());
}
通过Recreator.SavedStateProvider把AutoRecreated类class对象加入,Recreator.SavedStateProvider构造器进行了注册了本身,以达到AutoRecreated类的存储
3.2.3 数据管理
数据以androidx.lifecycle.BundlableSavedStateRegistry.key为key值,Bundle类型数据为value进行存储;SavedStateProvider中也是存储数据的对象,其saveState方法结果为存储值
存储方法
void performSave(@NonNull Bundle outBundle) {
Bundle components = new Bundle();
if (mRestoredState != null) {
components.putAll(mRestoredState);
}
for (Iterator<Map.Entry<String, SavedStateProvider>> it =
mComponents.iteratorWithAdditions(); it.hasNext(); ) {
Map.Entry<String, SavedStateProvider> entry1 = it.next();
components.putBundle(entry1.getKey(), entry1.getValue().saveState());
}
outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}
存储内容包括:已提出的上次存储内容、SavedStateProvider提供的数据,并且以当前新数据为准
取出方法
void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
if (mRestored) {
throw new IllegalStateException("SavedStateRegistry was already restored.");
}
if (savedState != null) {
mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
}
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;
}
提取数据,并感知生命周期记录是否需要存储状态,最后设置提取状态为true
数据消耗
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;
}
从已经解析的数据,并根据key值来取出
3.3 Recreator和其内部类
内部类SavedStateProvider完成AutoRecreated的存储,Recreator完成AutoRecreated的自动创建以及初始化
3.3.1 内部类SavedStateProvider
SavedStateProvider(final SavedStateRegistry registry) {
registry.registerSavedStateProvider(COMPONENT_KEY, this);
}
@NonNull
@Override
public Bundle saveState() {
Bundle bundle = new Bundle();
bundle.putStringArrayList(CLASSES_KEY, new ArrayList<>(mClasses));
return bundle;
}
void add(String className) {
mClasses.add(className);
}
自动注册当前provider到SavedStateRegistry实例,其对应key值为androidx.savedstate.Restarter,对应存储数据为Bundle实例;Bundle内容为以classes_to_restore为key值,以AutoRecreated集合为value
3.3.2 Recreator类
在数据恢复时,其进行了生命周期注册,其生命监听处理:
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (event != Lifecycle.Event.ON_CREATE) {
throw new AssertionError("Next event must be ON_CREATE");
}
source.getLifecycle().removeObserver(this);
Bundle bundle = mOwner.getSavedStateRegistry()
.consumeRestoredStateForKey(COMPONENT_KEY);
if (bundle == null) {
return;
}
ArrayList<String> classes = bundle.getStringArrayList(CLASSES_KEY);
if (classes == null) {
throw new IllegalStateException("Bundle with restored state for the component \""
+ COMPONENT_KEY + "\" must contain list of strings by the key \""
+ CLASSES_KEY + "\"");
}
for (String className : classes) {
reflectiveNew(className);
}
}
生命周期调用后,则不再进行监听;根据androidx.savedstate.Restarter消耗提取出来的数据,并提取classes_to_restore中class数组,并且其必须是AutoRecreated的子类;然后调用reflectiveNew方法自动初始化;处理流程中可以看出其和内部类是存储和解析的两个过程;且存储的是AutoRecreated的子类的类数组
4 viewmodel、viewmodel-savestate库
viewmodel库定义了viewmodel的基础框架;viewmodel-savestate库利用savestate库中留下的AutoRecreated接口以及SavedStateProvider接口来完成,viewmodel的数据存储与恢复
4.1 viewmodel库
相关类图如下:不复杂,就不对代码进行解读了
- ViewModel:对自身tag进行管理;并存在onCleard回调清理所有tag事件
- AndroidViewModel:Application级别viewModel
- ViewModelProvider:提供viewmodel类
- ViewModelProvider.Factory以及子类: viewModel生产工厂
- ViewModelProvider.OnRequeryFactory:对viewmodel中数据进行存储
- HasDefaultViewModelProviderFactory:ViewModelProvider.Factory工厂提供类
- ViewModelStore:viewmodel实例存储销毁管理
- ViewModelStoreOwner:ViewModelStore提供者
也就是提供了viewmodel的生产、存储、获取;其本身并没有实现什么特殊功能;ViewModelProvider进行获取,ViewmodelStore进行缓存,ViewModelProvider.Factory以及子类进行生产;进而又抽象出ViewModelStoreOwner、HasDefaultViewModelProviderFactory,也即ViewModelOwner持有者、制造工厂的创造者;
在此库中,ViewModel类中并没有实现数据的恢复等功能,但在activity、fragment生命周期中配置变化销毁中,进行了ViewmodelStore的存储,进而使得ViewModel有了配置销毁时数据保存能力;
4.2 viewmodel-savestate库
类图如下:
- ViewModelProvider.KeyedFactory实现类:viewModel工厂实现,并在onRequery方法中进行类中SavedStateHandle数据存储
- SavedStateHandle:ViewModel中数据存储与恢复类
- SavedStateHandleController:Viewmodel数据中控制类
其怎么保存与恢复数据呢,首先得从ViewModel工厂类来分析:AbstractSavedStateViewModelFactory抽象类在其它地方使用,就不分析了;而且数据必须可持久化(见SavedStateHandle.ACCEPTABLE_CLASSES中内容)
4.2.1 SavedStateViewModelFactory类
生产方法最终由下面方法产生
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);
}
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());
}
}
- 在找不到SavedStateHandle相关构造器时,使用内部工厂类进行生产(详情见构造器,这里不列出了)
- 生成SavedStateHandleController实例,生成viewmodel实例并设置tag为SavedStateHandleController实例
在SavedStateHandleController.create方法中进行了数据的恢复
4.2.2 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);
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
return controller;
}
- SavedStateRegistry中消耗数据;这里数据对应的key为viewmodel的class名字转化而来
- SavedStateHandle.createHandle创建SavedStateHandle对象,并依据参数恢复数据
- SavedStateHandleController实例创建,并进行生命周期监听,和数据提供者注册
- tryToAddRecreator:添加OnRecreation类到Recreator.SavedStateProvider中数据内,以便恢复数据时,自动执行;
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());
}
- 生命周期监听,记录生命周期状态,并在销毁后取消
- 并注册其相关联的Viewmodel中数据SavedStateHandle对象的状态提供者;这样其数据在需要存储时自动存入进去
tryToAddRecreator静态方法
此方法,只是为把OnRecreation类到Recreator.SavedStateProvider中数据内,以便恢复数据时,自动执行;不过对状态有限制,也就是onPause和onResume之间的时机
private static void tryToAddRecreator(SavedStateRegistry registry, Lifecycle lifecycle) {
Lifecycle.State currentState = lifecycle.getCurrentState();
if (currentState == INITIALIZED || currentState.isAtLeast(STARTED)) {
registry.runOnNextRecreation(OnRecreation.class);
} else {
lifecycle.addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_START) {
lifecycle.removeObserver(this);
registry.runOnNextRecreation(OnRecreation.class);
}
}
});
}
}
4.2.3 OnRecreation类
仅仅只有一个方法
@Override
public void onRecreated(@NonNull SavedStateRegistryOwner owner) {
if (!(owner instanceof ViewModelStoreOwner)) {
throw new IllegalStateException(
"Internal error: OnRecreation should be registered only on components"
+ "that implement ViewModelStoreOwner");
}
ViewModelStore viewModelStore = ((ViewModelStoreOwner) owner).getViewModelStore();
SavedStateRegistry savedStateRegistry = owner.getSavedStateRegistry();
for (String key : viewModelStore.keys()) {
ViewModel viewModel = viewModelStore.get(key);
attachHandleIfNeeded(viewModel, savedStateRegistry, owner.getLifecycle());
}
if (!viewModelStore.keys().isEmpty()) {
savedStateRegistry.runOnNextRecreation(OnRecreation.class);
}
}
自动执行时,如果viewModelStore内容未销毁,则通过attachHandleIfNeeded方法进行Viewmodel的生命周期和数据处理;这样就会在不需要工厂创建时完成数据恢复
SavedStateHandleController类中的静态方法attachHandleIfNeeded
static void attachHandleIfNeeded(ViewModel viewModel, SavedStateRegistry registry,
Lifecycle lifecycle) {
SavedStateHandleController controller = viewModel.getTag(
TAG_SAVED_STATE_HANDLE_CONTROLLER);
if (controller != null && !controller.isAttached()) {
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
}
}
通过tag获取SavedStateHandleController,并进行相应处理;详见上面对两个方法的分析
4.2.4 SavedStateHandle类
其中存储数据,还可以增加数据提供者,并且数据可以转换未liveData数据
存储过程
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<String, SavedStateProvider> map = new HashMap<>(mSavedStateProviders);
for (Map.Entry<String, SavedStateProvider> entry : map.entrySet()) {
Bundle savedState = entry.getValue().saveState();
set(entry.getKey(), savedState);
}
// Convert the Map of current values into a Bundle
Set<String> 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;
}
};
- 内部数据提供者在SavedStateHandleController中进行了注册
- 其数据包括了mSavedStateProviders的数据、mRegular数据
恢复过程
static SavedStateHandle createHandle(@Nullable Bundle restoredState,
@Nullable Bundle defaultState) {
if (restoredState == null && defaultState == null) {
return new SavedStateHandle();
}
Map<String, Object> state = new HashMap<>();
if (defaultState != null) {
for (String key : defaultState.keySet()) {
state.put(key, defaultState.get(key));
}
}
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);
}
在创建Viewmodel关联的SavedStateHandleController实例时创建,restoredState为已经解析的数据,defaultState为启动时附带数据;附带数据全部解析,restoredState取出相应key值;却没有取出所有相关mSavedStateProviders中数据,这需要这些实例主动去获取其值(暂时未见使用,可能是预留);这些数据全部存储在类变量mRegular中
LiveData实例获取
其本质上都是通过下面方法实现
private <T> MutableLiveData<T> getLiveDataInternal(
@NonNull String key,
boolean hasInitialValue,
@Nullable T initialValue) {
MutableLiveData<T> liveData = (MutableLiveData<T>) mLiveDatas.get(key);
if (liveData != null) {
return liveData;
}
SavingStateLiveData<T> mutableLd;
// double hashing but null is valid value
if (mRegular.containsKey(key)) {
mutableLd = new SavingStateLiveData<>(this, key, (T) mRegular.get(key));
} else if (hasInitialValue) {
mutableLd = new SavingStateLiveData<>(this, key, initialValue);
} else {
mutableLd = new SavingStateLiveData<>(this, key);
}
mLiveDatas.put(key, mutableLd);
return mutableLd;
}
- 是否已有缓存,mLiveDatas存着的即为缓存
- 生成LiveDatas实例,其类为SavingStateLiveData:同步变化mRegular中相应数据
为何要同步变化呢,因为livedata内数据,就是根据mRegular中变化,这样可以同步保存以便恢复时为正确内容
数据变化
public <T> T get(@NonNull String key) {
return (T) mRegular.get(key);
}
public <T> void set(@NonNull String key, @Nullable T value) {
validateValue(value);
@SuppressWarnings("unchecked")
MutableLiveData<T> mutableLiveData = (MutableLiveData<T>) mLiveDatas.get(key);
if (mutableLiveData != null) {
mutableLiveData.setValue(value);
} else {
mRegular.put(key, value);
}
}
public <T> T remove(@NonNull String key) {
@SuppressWarnings("unchecked")
T latestValue = (T) mRegular.remove(key);
SavingStateLiveData<?> liveData = mLiveDatas.remove(key);
if (liveData != null) {
liveData.detach();
}
return latestValue;
}
保持mRegular和mLiveDatas中数据同步变化;也是为了保存正确且必要的数据
SavingStateLiveData类
public void setValue(T value) {
if (mHandle != null) {
mHandle.mRegular.put(mKey, value);
}
super.setValue(value);
}
void detach() {
mHandle = null;
}
其中数据变动保持与持有mHandle对象内保持一致;由于数据变动可以来在LiveData实例,所以在此能确保数据如何变化都会保持同步
5 小结
- LiveData如果不需要在配置变化或者异常销毁时恢复,则没有必要和ViewModel关联;
- ViewModel直接定义的变量可在配置变化时重新恢复;
- ViewModel可以增加子类,提供存在([Application,]SavedStateHandle)的构造器,在内部数据可以在异常情况下恢复,其数据必须满足相应要求;这种方式不适合在配置变化时使用,如需要按照2来做
- ViewModel使用ViewModelProvider实例来获取,ViewModelProvider参数来自持有者
技术变化都很快,但基础技术、理论知识永远都是那些;作者希望在余后的生活中,对常用技术点进行基础知识分享;如果你觉得文章写的不错,请给与关注和点赞;如果文章存在错误,也请多多指教!