JetPack框架组件3——ViewModel的使用和源码分析
文章目录
- JetPack框架组件3——ViewModel的使用和源码分析
一.ViewModel的使用和概述
1.使用场景
ViewModel是什么,ViewModel就是Activity/Fragment中的一个实体,是为了帮助Activity/fragmet承担业务逻辑,负责activity和model的沟通,承担资源的获取和释放工作,让activity和只承担ui变化的逻辑。
2.ViewModel生命周期
下图是ViewModel的生命周期
ViewModel的存在时间范围是和获取到ViewModel传递的Lifecycle相关联。也就是说,在Lifecycle彻底消失前。ViewModel将会一直存在于内存中。
- 对于Activity来说,是activity完成时
- 对于fragment来说,是fragment分离时
所以基于ViewModel生命周期的特点,所以ViewModel具有下面的特点:
- 可以避免内存泄露。在Activity.onDestroy时会关联ViewModel.onCleared()方法,从而在这里释放内存。
- 在设备发生配置更改时(如:屏幕旋转),可以用ViewModel保存一些数据,不需要重新获取
- 可以使用ViewModel再fragment直接共享数据(activityViewModels)
3.使用
定义ViewModel
class NameViewModel :ViewModel() {
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
}
获取和使用ViewModel
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false)
}
// 获取ViewModels
private val model: NameViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val nameObserver = Observer<String> { newName ->
textview_first.text = newName
}
model.currentName.observe(this, nameObserver)
view.findViewById<Button>(R.id.button_first).setOnClickListener {
val anotherName = "John Doe"
//调用ViewModel
model.currentName.setValue(anotherName)
}
}
}
4.ViewModel 关键类
ViewModel有两个关键的类,一个是ViewModelStore负责存储ViewModel,一个是ViewModelFactor负责生产ViewModel
所以我们看源码主要带着下面的问题看
- ViewModelStore是如何获取到的,ViewModelStore如何存储ViewModel
- ViewModelFactor是如何获取到的,ViewModelFactor是如何生产ViewModel
- ViewModel的获取全链路
- ViewModel在设备状态改变时(屏幕状态改变),如何保证数据不丢失的
二.ViewModelStore的获取
1.获取ViewModel的入口
ViewModel的入口方法:
private val model: NameViewModel by viewModels()
进入看看实现:
FragmentViewModelLazy
@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
//负责生产ViewModel,可以自定义实现
noinline factoryProducer: (() -> Factory)? = null
//ownerProducer().viewModelStore 负责存储ViewModel
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
2.ViewModelStore的定义
在看获取之前,我们先看看ViewModelStore的定义
public class ViewModelStore {
//所以ViewModelStore本质就是一个hasMap
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
由上面可以看出。ViewModelStore本质是一个封装的hasmap。
3.Activity中获取ViewModelStore
ownerProducer()的实现类在fragment中,我们往下看
public class ComponentActivity extends androidx.core.app.ComponentActivity {
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) {
// 从nc中恢复viewModelStore
mViewModelStore = nc.viewModelStore;
}
//没有的话,重新创造一个
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
}
从源码里可以看出来,ViewModelStore优先从NonConfigurationInstances中获取,那么NonConfigurationInstances是什么呢,看下NonConfigurationInstances的定义
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
}
NonConfigurationInstances是一个包装类,简单的将viewModelStore和custom包装了一下
我们看一下LastNonConfigurationInstance是如何获取的
public class Activity extends ContextThemeWrapper {
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
}
总结:最终nc就是activity.mLastNonConfigurationInstances
4.Fragment中获取ViewModelStore
ownerProducer()的实现类在fragment中,我们继续往下看
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
ViewModelStoreOwner, SavedStateRegistryOwner {
....
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (mFragmentManager == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
return mFragmentManager.getViewModelStore(this);
}
...
}
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
...
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
//这里的mNonConfig也是ViewModel是实现类
return mNonConfig.getViewModelStore(f);
}
....
}
继续往下,如何从FragmentManagerViewModel中获取ViewModelStore
//这里也是ViewModel
class FragmentManagerViewModel extends ViewModel {
private final HashMap<String, ViewModelStore> mViewModelStores = new HashMap<>();
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
//看看是否有缓存的viewModelStore
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore == null) {
//没有的话重新创建一个
viewModelStore = new ViewModelStore();
mViewModelStores.put(f.mWho, viewModelStore);
}
return viewModelStore;
}
}
再看看mNonConfig(FragmentManagerViewModel)是如何创建的
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
public void attachController(@NonNull FragmentHostCallback host,
@NonNull FragmentContainer container, @Nullable final Fragment parent) {
// Get the FragmentManagerViewModel
if (parent != null) {
mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
//如果 host是ViewModelStoreOwner
} else if (host instanceof ViewModelStoreOwner) {
ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
} else {
mNonConfig = new FragmentManagerViewModel(false);
}
}
@NonNull
FragmentManagerViewModel getChildNonConfig(@NonNull Fragment f) {
return mNonConfig.getChildNonConfig(f);
}
}
class FragmentManagerViewModel extends ViewModel {
static FragmentManagerViewModel getInstance(ViewModelStore viewModelStore) {
ViewModelProvider viewModelProvider = new ViewModelProvider(viewModelStore,
FACTORY);
return viewModelProvider.get(FragmentManagerViewModel.class);
}
//获取子Fragment的FragmentManagerViewModel
FragmentManagerViewModel getChildNonConfig(@NonNull Fragment f) {
FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho);
if (childNonConfig == null) {
childNonConfig = new FragmentManagerViewModel(mStateAutomaticallySaved);
mChildNonConfigs.put(f.mWho, childNonConfig);
}
return childNonConfig;
}
}
5.小结
- ViewModel本质是一个hasMap
- 如果是在Activity中获取ViewModelStore,它会优先在activity.mLastNonConfigurationInstances中获取ViewModelStore。
- 如果是在Fragment中获取ViewModelStore,他会从FragmentManagerViewModel中获取这个Fragment对应的ViewModelStore
- FragmentManagerViewModel本质也是一个ViewModel,FragmentManagerViewModel是在FragmentManagerImpl.attachController()中被创建出来
三.ViewModelFactor的获取
1.获取ViewModelFactor的入口
上一节我们知道,获取ViewModel的入口,在下面
FragmentViewModelLazy
@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
//负责生产ViewModel,可以自定义实现
noinline factoryProducer: (() -> Factory)? = null
//ownerProducer().viewModelStore 负责存储ViewModel
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
我们继续往下看
FragmentViewModelLazy
@MainThread
fun <VM : ViewModel> Fragment.createViewModelLazy(
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
val application = activity?.application ?: throw IllegalStateException(
"ViewModel can be accessed only when Fragment is attached"
)
//获取默认的AndroidViewModelFactory
AndroidViewModelFactory.getInstance(application)
}
return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
}
2.默认的ViewModelFactor - AndroidViewModelFactory
获取FragmentViewModelLazy
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private static AndroidViewModelFactory sInstance;
//单例
@NonNull
public static AndroidViewModelFactory getInstance(@NonNull Application application) {
if (sInstance == null) {
sInstance = new AndroidViewModelFactory(application);
}
return sInstance;
}
private Application mApplication;
public AndroidViewModelFactory(@NonNull Application application) {
mApplication = application;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//反射获取ViewModel
try {
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}
}
3.小结
- ViewModelFactor如果没有自定义,就会生成默认的工厂类AndroidViewModelFactory
- AndroidViewModelFactory中ViewModel是通过反射获取ViewModel
四.ViewModel的获取
上两节我们看了存储ViewModel的ViewModelStore的获取,和一个生产ViewModel的ViewModelFactor的获取。下面我们完整的梳理一下ViewModel的获取
1.入口
FragmentViewModelLazy
@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
//负责生产ViewModel,可以自定义实现
noinline factoryProducer: (() -> Factory)? = null
//ownerProducer().viewModelStore 负责存储ViewModel
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
我们继续往下看
FragmentViewModelLazy
@MainThread
fun <VM : ViewModel> Fragment.createViewModelLazy(
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
val application = activity?.application ?: throw IllegalStateException(
"ViewModel can be accessed only when Fragment is attached"
)
//获取默认的AndroidViewModelFactory
AndroidViewModelFactory.getInstance(application)
}
return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
}
继续往下看
class ViewModelLazy<VM : ViewModel> (
private val viewModelClass: KClass<VM>,
private val storeProducer: () -> ViewModelStore,
private val factoryProducer: () -> ViewModelProvider.Factory
) : Lazy<VM> {
private var cached: VM? = null
override val value: VM
get() {
//有缓存先获取缓存
val viewModel = cached
return if (viewModel == null) {
val factory = factoryProducer()
val store = storeProducer()
//这里获取新的ViewModel
ViewModelProvider(store, factory).get(viewModelClass.java).also {
cached = it
}
} else {
viewModel
}
}
override fun isInitialized() = cached != null
}
2.ViewModelProvider
在ViewModelProvider获取ViewModel
public class ViewModelProvider {
@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);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//优先从mViewModelStore获取ViewModel
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
//如果没有就从mFactory中new一个
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
}
3.小结
ViewModel的获取是在ViewModelProvider中获取的
- ViewModel优先从ViewModelStore中获取
- 如果mViewModelStore没有,就通过mFactory中新创建一个
五.ViewModel的恢复
上面我们完整的看完了一个viewModel的获取流程,但是我们最开始的疑问还是没有解决:
- ViewModel在设备状态改变时(屏幕状态改变),如何保证数据不丢失的
下面我们就来看这个问题
再这之前,先回顾一个之前看代码的细节:
Activity中获取ViewModelStore,它会优先在activity.mLastNonConfigurationInstances中获取
这里的mLastNonConfigurationInstances和我们要看的内容息息相关
1.保存
我们看一下,在发生设备状态改变时的回调。
ActivityThread.performDestroyActivity()
public final class ActivityThread extends ClientTransactionHandler {
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = mActivities.get(token);
...
if (r != null) {
....
if (getNonConfigInstance) {
try {
//保存lastNonConfigurationInstances变量
r.lastNonConfigurationInstances
= r.activity.retainNonConfigurationInstances();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to retain activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
...
return r;
}
}
当设备状态发生改变时,Lifecycle状态改变为ON_DESTROY的会调
public class ComponentActivity extends androidx.core.app.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();
}
}
}
});
}
}
2.恢复
当配置更改发生后,如何再次恢复
ActivityThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
...
try {
...
//这里我们可以看到,将lastNonConfigurationInstances传入activity中
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
...
} catch (SuperNotCalledException e) {
...
} catch (Exception e) {
...
}
return activity;
}
attach方法
@UnsupportedAppUsage
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
.....
//完成赋值
mLastNonConfigurationInstances = lastNonConfigurationInstances;
....
}
3.小结
ViewModel的恢复其实本质就是在配置信息发生改变后,在activity销毁前,将其保存,然后再activity重建后,将其恢复。
4.其他
资源不足,或者后台进程关闭后所导致的activity被回收,viewModel是否可以将数据恢复
答:不可以,但是可以支持
使用SavedStateHandle
六.ViewModel与SavedStateHandle
1.SavedStateHandle的介绍
我们知道如果资源不足,或者后台进程关闭后所导致的activity被回收,viewModel是不可以将数据恢复。如果此时想让数据恢复,我们就要引入SavedStateHandle
所以onSaveInstanceState方法能保存的数据的场景:
- 由于资源限制,Activity被系统杀掉;
- 配置更改。
onSaveInstanceState特点:
onSaveInstanceState方法只能保存少量简单的数据,大量和复杂数据最后不要放在onSaveInstanceState方法保存。因为onSaveInstanceState方法是通过Bundle保存数据,如果数据的量太大或者太复杂,会阻塞UI线程,从而影响Activity生命周期的执行。
2.SavedStateHandle的使用
SavedStateHandle的使用比较简单
定义ViewModerl
class NameWithSaveViewModel(private val saveStateHandle: SavedStateHandle) :ViewModel() {
// 需要在资源限制导致重建的场景下保存的数据
// 用LiveData暴露,不能让外部直接通过LiveData去修改内部的值
val mAgeLiveData: LiveData<Int> = saveStateHandle.getLiveData(KEY_AGE)
fun setAge(age: Int) {
saveStateHandle.set(KEY_AGE, age)
}
companion object {
const val KEY_AGE = "key_age";
}
}
创建ViewModel对下,使用VeiwModel
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//创建Viewmodel
val viewModel = ViewModelProvider(
this,
SavedStateViewModelFactory(activity?.application, this)
)[NameWithSaveViewModel::class.java]
view.findViewById<Button>(R.id.button_first).setOnClickListener {
//保存数据
viewModel.setAge(1)
}
}
}
3.SavedStateHandle相关类
和SavedStateHandle 相关有四个类,SavedStateRegistryOwner,SavedStateRegistryController,SavedStateRegistry,SavedStateProvider。
我们分别看看这四个类的作用
- SavedStateRegistryOwner: 接口,有一个getSavedStateRegistry方法,作用是提供SavedStateRegistry对象。该接口主要实现类有Activity和Fragment。
- SavedStateRegistryController: SavedStateRegistry的控制类,主要有两个方法:performRestore方法的作用恢复数据;performSave方法主要保存数据。Activity和Fragment直接操作类就是该类。
- SavedStateRegistry:主要是从Activity或者Fragment等)恢复数据,或者需要保存的数据写入UI控制器的Bundle里面。SavedStateRegistryController主要操作类就是该类。
- SavedStateProvider: 主要是提供保存和恢复的数据。该接口只有一个saveState方法,主要的作用将需要保存的数据用Bundle包装起来。
我们在ComponentActivity看看SavedStateHandle如何工作的
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
private final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
// ······
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
// ······
}
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
// ······
mSavedStateRegistryController.performSave(outState);
}
// ······
}
从上面的代码我们可以看出来:SavedStateRegistryController主要分为两个过程:
- 在onCreate方法调用了performRestore方法,主要的作用是恢复已保存的数据。
- 在onDestroy方法调用了performSave方法,主要的作用保存数据。
4.SavedStateHandle保存数据
入口代码:
mSavedStateRegistryController.performSave(outState);
SavedStateRegistryController中
public final class SavedStateRegistryController {
private final SavedStateRegistryOwner mOwner;
private final SavedStateRegistry mRegistry;
@MainThread
public void performSave(@NonNull Bundle outBundle) {
mRegistry.performSave(outBundle);
}
}
在SavedStateRegistr中
public final class SavedStateRegistry {
@MainThread
void performSave(@NonNull Bundle outBundle) {
Bundle components = new Bundle();
if (mRestoredState != null) {
components.putAll(mRestoredState);
}
//SavedStateProvider
for (Iterator<Map.Entry<String, SavedStateProvider>> it =
mComponents.iteratorWithAdditions(); it.hasNext(); ) {
Map.Entry<String, SavedStateProvider> entry1 = it.next();
//saveState需要保存的数据
components.putBundle(entry1.getKey(), entry1.getValue().saveState());
}
outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}
}
SavedStateProvider定义
public interface SavedStateProvider {
@NonNull
Bundle saveState();
}
- 如果mRestoredState不为空,表示之前恢复的数据还没有被消费完,需要将没有消费的数据再一次保存。
- 遍历所有注册的SavedStateProvider,将所有的SavedStateProvider提供的数据保存起来。
- 将所有保存的数据全部写入到Activity的Bundle对象。
5.SavedStateHandle恢复数据
入口代码
mSavedStateRegistryController.performRestore(savedInstanceState);
SavedStateRegistryController中
public final class SavedStateRegistryController {
private final SavedStateRegistryOwner mOwner;
private final SavedStateRegistry mRegistry;
@MainThread
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);
}
}
在SavedStateRegistr中
public final class SavedStateRegistry {
@MainThread
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;
}
}
目前是将数据保持在mRestoredState,但并没有给ViewModel。什么时候赋值给ViewMoedl,我们换个角度看看,从VIewModel的重新创建看起。在SavedStateHandle场景中,ViewModel的工厂类是SavedStateViewModelFactory。我们看看此时ViewModel的创建
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor<T> constructor;
//获取viewmodel的modelClass
if (isAndroidViewModel && mApplication != null) {
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
...
//创建controller
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
if (isAndroidViewModel && mApplication != null) {
//创建viewmodel对象
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) {
...
}
}
}
我们看看SavedStateHandleController中做了什么
final class SavedStateHandleController implements LifecycleEventObserver {
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
//获取之前保存的Bundle
Bundle restoredState = registry.consumeRestoredStateForKey(key);
SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//将SavedStateHandle的SavedStateProvider注册到SavedStateRegistry
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
return controller;
}
}
在SavedStateRegistr中
public final class SavedStateRegistry {
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;
}
//返回恢复的Bundle
return result;
}
return null;
}
}
小结:
1.在activityd的onCreate 通过SavedStateHandleController恢复之前保持的数据
2.在SavedStateHandle场景中,ViewModel的工厂类是SavedStateViewModelFactory,此时ViewModel通过SavedStateViewModelFactory创建
3.在ViewModel的create中通过SavedStateHandleController获得之前保存的数据
4.ViewModel根据之前获得的数据,通过反射方式创建一个新的ViewModel