??Jetpack已經(jīng)出了很久很久了,近幾年的GDD幾乎每次都會(huì)介紹新的組件,說(shuō)來(lái)慚愧,一直沒有好好學(xué)習(xí),看近年的Google 的很多Demo中其實(shí)都有所體現(xiàn),之前都是大概的了解了一遍。最近決定,好好梳理一遍,既學(xué)習(xí)其用法,也嘗試學(xué)習(xí)下其設(shè)計(jì)思想。也是時(shí)候該補(bǔ)充一下了。進(jìn)入正題--ViewModel
??首先都是看官方的例子,ViewModel官方的的例子是會(huì)和另一個(gè)架構(gòu)庫(kù)LiveData寫在一起,很多的博客也是照官方的例子來(lái)說(shuō)明,開始接觸時(shí)甚至給了我一種假象:ViewModel都是和LiveData一起使用的。后來(lái)閱讀才了解,ViewModel和LiveData職責(zé)分工還是很明顯的,使用LiveData Demo主要使用其observe功能,LiveDate的使用及原理之后再分析,甚至在appcompat-v7:27.1.1中直接單獨(dú)集成了ViewModel.所以,故為排除干擾,今天不會(huì)使用官方的主流Demo用法,先來(lái)看ViewModel。
??Android的UI控制器(Activity和Fragment)從創(chuàng)建到銷毀擁有自己完整的生命周期,當(dāng)系統(tǒng)配置發(fā)生改變時(shí)((Configuration changes)),系統(tǒng)就會(huì)銷毀Activity和與之關(guān)聯(lián)的Fragment然后再次重建<font color=#FFA500>(可通過(guò)在AndroidManifast.xml中配置android:configChanges修改某些行為,這里不討論)</font>,那么存儲(chǔ)在當(dāng)前UI中的臨時(shí)數(shù)據(jù)也會(huì)被清空,例如,登陸輸入框,輸入賬號(hào)或密碼后旋轉(zhuǎn)屏幕,視圖被重建,輸入過(guò)的數(shù)據(jù)也清空了,這無(wú)疑是一種不友好的用戶體驗(yàn)。對(duì)于少量的可序列化數(shù)據(jù)可以使用onSaveInstanceState()方法保存然后在onCreate()方法中重新恢復(fù),正如所說(shuō)onSaveInstanceState對(duì)于大量的數(shù)據(jù)緩存有一定的局限性,大量的數(shù)據(jù)緩存則可以使用Fragment.setRetainInstance(true)來(lái)保存數(shù)據(jù)。ViewModel也是提供了相同的功能,其實(shí)和“RetainInstance”也有關(guān)聯(lián),用來(lái)存儲(chǔ)和管理與UI相關(guān)的數(shù)據(jù),允許數(shù)據(jù)在系統(tǒng)配置變化后存活,我們一起看一下這個(gè)ViewModel的緩存是怎么實(shí)現(xiàn)的呢?
使用方式
首先先看下使用方式,先上效果圖
public class MyViewModel extends ViewModel {
String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
@Override
protected void onCleared() {
super.onCleared();
name = null;
}
}
?
public class ViewModelActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "ViewModelActivity";
TextView textView;
private MyViewModel myViewModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewmodel);
textView = findViewById(R.id.textView);
textView.setOnClickListener(this);
ViewModelProvider.Factory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication());
/*
*這里的this是ViewModelStoreOwner接口在appcompat-v7:27.1.1支持庫(kù)中AppCompatActivity已經(jīng)實(shí)現(xiàn)了,
*如果是較低版本,需要更新支持包或者參考其實(shí)現(xiàn)對(duì)本來(lái)繼承的Activity做對(duì)應(yīng)實(shí)現(xiàn)。
*/
ViewModelProvider provider = new ViewModelProvider(this, factory);//
myViewModel = provider.get(MyViewModel.class);
Log.e(TAG, "onCreate: " + myViewModel.getName() );
if (myViewModel.getName() != null) {
textView.setText(myViewModel.getName());
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.textView:
myViewModel.setName("MyViewModel Test");
textView.setText(myViewModel.getName());
break;
}
}
}
?
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="default"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
非常簡(jiǎn)單的一個(gè)例子,這就是ViewModel最簡(jiǎn)單的使用了,就是TextView中顯示ViewModel的數(shù)據(jù)。ViewModel需要由ViewModelProvider.get(Class<T>)來(lái)取得,旋轉(zhuǎn)屏幕銷毀后,之前改變的數(shù)據(jù)還在。
發(fā)現(xiàn)的一些疑問(wèn)
接下來(lái)就是進(jìn)入主題分析下ViewModel到底是怎么實(shí)現(xiàn)的呢?
帶著問(wèn)題看源碼:
- ViewModelProvider是干啥的?
- AndroidViewModelFactory 這命名一看就是應(yīng)該是工廠模式,工廠創(chuàng)建了什么?
- provider.get(MyViewModel.class) 這里直接使用的get命名就得到了需要的唯一數(shù)據(jù)
- 注釋中ViewModelStoreOwner又是什么角色?
源碼分析
先看ViewModel類,沒什么說(shuō)的,就是一個(gè)么有任何真正實(shí)現(xiàn)的抽象類,只有一個(gè)抽象方法onCleared()
public abstract class ViewModel {
/**
* This method will be called when this ViewModel is no longer used and will be destroyed.
* <p>
* It is useful when ViewModel observes some data and you need to clear this subscription to
* prevent a leak of this ViewModel.
*/
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
}
}
接著看下ViewModelFactory,顧名思義就是制造ViewModel的。
AndroidViewModelFactory的繼承關(guān)系如下:
android.arch.lifecycle.ViewModelProvider.Factory
android.arch.lifecycle.ViewModelProvider.NewInstanceFactory
android.arch.lifecycle.ViewModelProvider.AndroidViewModelFactory
Factory是一個(gè)只包含一個(gè)create的interface,NewInstanceFactory實(shí)現(xiàn)了該方法傳入Class<T>會(huì)利用ViewModel的默認(rèn)無(wú)參構(gòu)造器創(chuàng)建一個(gè)對(duì)應(yīng)ViewModel的實(shí)例,而AndroidViewModelFactory增加了一個(gè)屬性就是應(yīng)用的Applicaion,同時(shí)重寫create方法,查看ViewModel是否有包含Applicaion參數(shù)的構(gòu)造方法從而使用,對(duì)應(yīng)的其實(shí)還有一個(gè)AndroidViewModel是ViewModel的子類,默認(rèn)已經(jīng)實(shí)現(xiàn)了帶有Application參數(shù)的構(gòu)造方法,需要使用在ViewModel中使用application的直接繼承AndroidViewModel就可以,看到這里其實(shí)最上面的例子有個(gè)不是問(wèn)題的問(wèn)題,其實(shí)上面的Factory直接使用NewInstanceFactory就可以創(chuàng)建出對(duì)應(yīng)的ViewModel實(shí)例了。
/**
* Implementations of {@code Factory} interface are responsible to instantiate ViewModels.
*/
public interface Factory {
/**
* Creates a new instance of the given {@code Class}.
* <p>
*
* @param modelClass a {@code Class} whose instance is requested
* @param <T> The type parameter for the ViewModel.
* @return a newly created ViewModel
*/
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
/**
* Simple factory, which calls empty constructor on the give class.
*/
public static class NewInstanceFactory implements Factory {
@SuppressWarnings("ClassNewInstance")
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
}
/**
* {@link Factory} which may create {@link AndroidViewModel} and
* {@link ViewModel}, which have an empty constructor.
*/
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private static AndroidViewModelFactory sInstance;
/**
* Retrieve a singleton instance of AndroidViewModelFactory.
*
* @param application an application to pass in {@link AndroidViewModel}
* @return A valid {@link AndroidViewModelFactory}
*/
@NonNull
public static AndroidViewModelFactory getInstance(@NonNull Application application) {
if (sInstance == null) {
sInstance = new AndroidViewModelFactory(application);
}
return sInstance;
}
private Application mApplication;
/**
* Creates a {@code AndroidViewModelFactory}
*
* @param application an application to pass in {@link AndroidViewModel}
*/
public AndroidViewModelFactory(@NonNull Application application) {
mApplication = application;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
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);
}
}
之后通過(guò)ViewModelStoreOwner和剛剛創(chuàng)建的Factory創(chuàng)建出ViewModelPrivider實(shí)例
/**
* Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the given
* {@code Factory} and retain them in a store of the given {@code ViewModelStoreOwner}.
*
* @param owner a {@code ViewModelStoreOwner} whose {@link ViewModelStore} will be used to
* retain {@code ViewModels}
* @param factory a {@code Factory} which will be used to instantiate
* new {@code ViewModels}
*/
public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
this(owner.getViewModelStore(), factory);
}
/**
* Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the given
* {@code Factory} and retain them in the given {@code store}.
*
* @param store {@code ViewModelStore} where ViewModels will be stored.
* @param factory factory a {@code Factory} which will be used to instantiate
* new {@code ViewModels}
*/
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
this.mViewModelStore = store;
}
/**
* A scope that owns {@link ViewModelStore}.
* <p>
* A responsibility of an implementation of this interface is to retain owned ViewModelStore
* during the configuration changes and call {@link ViewModelStore#clear()}, when this scope is
* going to be destroyed.
*/
@SuppressWarnings("WeakerAccess")
public interface ViewModelStoreOwner {
/**
* Returns owned {@link ViewModelStore}
*
* @return a {@code ViewModelStore}
*/
@NonNull
ViewModelStore getViewModelStore();
}
ViewModelStoreOwner 也是一個(gè)接口是FragmentActivity實(shí)現(xiàn)了該接口并實(shí)現(xiàn)了其中的getViewModelStore()方法
public class FragmentActivity extends BaseFragmentActivityApi16 implements
ViewModelStoreOwner...{
private ViewModelStore mViewModelStore;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mViewModelStore = nc.viewModelStore;
}
/**
* Returns the {@link ViewModelStore} associated with this activity
*
* @return a {@code ViewModelStore}
*/
@NonNull
@Override
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) {
mViewModelStore = new ViewModelStore();
}
return mViewModelStore;
}
}
這個(gè)ViewModelStore又是什么呢,其實(shí)就是真正利用HashMap存儲(chǔ)ViewModel的地方了,看下代碼在存儲(chǔ)和clear同時(shí)會(huì)調(diào)用ViewModel需要實(shí)現(xiàn)的抽象方法onClear()
public class ViewModelStore {
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);
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
}
這樣ViewModelProvider就是有了一個(gè)ViewModel的容器,這時(shí)去調(diào)用ViewModelProvider的get(Class<T>)方法就是去調(diào)用mViewModelStore
的get()方法取出對(duì)應(yīng)的ViewModel所以這里只要持有的ViewModelStore是有緩存的,那么取出的ViewModel就是相同的緩存了。
/**
* Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
* an activity), associated with this {@code ViewModelProvider}.
* <p>
* The created ViewModel is associated with the given scope and will be retained
* as long as the scope is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
* @param modelClass The class of the ViewModel to create an instance of it if it is not
* present.
* @param <T> The type parameter for the ViewModel.
* @return A ViewModel that is an instance of the given type {@code T}.
*/
@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) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
看到這里就會(huì)發(fā)現(xiàn)ViewModelStore的緩存其實(shí)是通過(guò)NonConfigurationInstances的緩存來(lái)實(shí)現(xiàn)的,這樣就完成了Activity銷毀重建后ViewModel還保存原來(lái)的數(shù)據(jù)的過(guò)程,那么NonConfigurationInstances 是什么呢?如果有了解過(guò)使用在Activity中使用onRetainNonConfigurationInstance()保存緩存數(shù)據(jù),在onCreate()中通過(guò)getLastNonConfigurationInstance()恢復(fù)之前的數(shù)據(jù)狀態(tài)的同學(xué)可能會(huì)很熟悉這里的寫法,是的,這里FragmentActivity就是使用的這種方式來(lái)保存之前的ViewModelStore,看下FragmentActivity的onRetainNonConfigurationInstance()方法。
/**
* Retain all appropriate fragment state. You can NOT
* override this yourself! Use {@link #onRetainCustomNonConfigurationInstance()}
* if you want to retain your own state.
*/
@Override
public final Object onRetainNonConfigurationInstance() {
if (mStopped) {
doReallyStop(true);
}
Object custom = onRetainCustomNonConfigurationInstance();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
if (fragments == null && mViewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = mViewModelStore;//就是這里了,會(huì)把之前的VeiwmodelStroe存儲(chǔ)到NonConfigurationInstances中以供后續(xù)恢復(fù)使用
nci.fragments = fragments;
return nci;
}
這里其實(shí)再次出現(xiàn)了一個(gè)問(wèn)題 onRetainNonConfigurationInstance()和getLastNonConfigurationInstance()又是怎么恢復(fù)數(shù)據(jù)呢?...這個(gè)其實(shí)和Activity的啟動(dòng)流程相關(guān),這里也介紹一下吧,之后的內(nèi)容其實(shí)是Activity的內(nèi)容了,趁這次看ViwModel也跟著看了一遍,有了解過(guò)Activity啟動(dòng)流程的同學(xué)更容易理解的多,大家酌情觀看。
也不能從頭開始說(shuō)起,再?gòu)念^就要越扯越遠(yuǎn)了,就從ActivityThread.java中的scheduleLaunchActivity開始
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
從ActivityThread.java中H(extents Handler)接收到LAUNCH_ACTIVITY,并且會(huì)接收ActivityClientRecord,其中會(huì)調(diào)用ActivityThread的handleLaunchActivity方法:
//ActivityThread.java
//沒有前后文的H中的handleMessage~~~
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//ActivityClientRecord 是apk進(jìn)程中一個(gè)Activity的代表,這個(gè)對(duì)象的activity成員引用真正的Activity組件,后面的都和它有關(guān)系
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");///這里~這里~
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);
...
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config, //看到這個(gè)r.lastNonConfigurationInstances 就是在Activity方法中調(diào)用getLastNonConfigurationInstance()獲取到的Object了。
r.referrer, r.voiceInteractor, window, r.configCallback);
...
}
注釋中的地方就是lastNonConfigurationInstances的賦值的地方,可能會(huì)發(fā)現(xiàn)在scheduleLaunchActivity并沒有對(duì)lastNonConfigurationInstances賦值,因?yàn)榈谝淮螁?dòng)Activity時(shí),這里其實(shí)就是null的,那么賦值的地方在哪里呢,既然是銷毀后會(huì)恢復(fù)數(shù)據(jù),追蹤發(fā)現(xiàn)在performDestroyActivity()也就是在調(diào)用onDestroy生命周期之前有這樣一段代碼
private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = mActivities.get(token);
...無(wú)關(guān)代碼省略
if (getNonConfigInstance) {
try {
r.lastNonConfigurationInstances
= r.activity.retainNonConfigurationInstances();///就是這里出現(xiàn)了想要找的NonConfigurationInstances
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to retain activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnDestroy(r.activity);
...無(wú)關(guān)代碼省略
return r;
}
在performDestroyActivity()調(diào)用了Activity.retainNonConfigurationInstances()方法了,所以邏輯切換回Activity中...
/**
* This method is similar to {@link #onRetainNonConfigurationInstance()} except that
* it should return either a mapping from child activity id strings to arbitrary objects,
* or null. This method is intended to be used by Activity framework subclasses that control a
* set of child activities, such as ActivityGroup. The same guarantees and restrictions apply
* as for {@link #onRetainNonConfigurationInstance()}. The default implementation returns null.
*/
@Nullable
HashMap<String,Object> onRetainNonConfigurationChildInstances() {
return null;
}
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();///熟悉的代碼,原來(lái)的配方,和分析ActivityThread之前聯(lián)系起來(lái)了,在Activity中是空實(shí)現(xiàn),這里就是獲取子類的NonConfigurationInstance(),之前的例子就是的得FragmentActivity中的具體實(shí)現(xiàn),上文中已經(jīng)在分析ActivityThread.java已經(jīng)指出。
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
// We're already stopped but we've been asked to retain.
// Our fragments are taken care of but we need to mark the loaders for retention.
// In order to do this correctly we need to restart the loaders first before
// handing them off to the next activity.
mFragments.doLoaderStart();
mFragments.doLoaderStop(true);
ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
if (activity == null && children == null && fragments == null && loaders == null
&& mVoiceInteractor == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;//這里返回的是Activity中的NonConfigurationInstances就保存在了ActivityClientRecord中了
}
至此,ActivityClientRecord就不再深入了,可以看到在Activity中是以一個(gè)ArrayMap來(lái)保存Activity的記錄,記錄的就是Activity的狀態(tài),所以這里就實(shí)現(xiàn)了對(duì)NonConfigurationInstances的保存。
結(jié)語(yǔ):至此就基本看完了ViewModel在Activity中的使用和原理,在Fragment中的實(shí)現(xiàn)主要是使用setRetainInstance(true)的方式去保存,跟今天的分析也有關(guān)聯(lián),分析源碼的過(guò)程總是看著就有新的問(wèn)題,再次帶著問(wèn)題去解決會(huì)再次有不同的收獲,本文的理解也可能有偏差,如有錯(cuò)誤和想要交流的也歡迎指正溝通。