目录
- Activity创立ViewModel
-
Activity重建ViewModel坚持存在的完成
- relaunch之后新的Activity获取之前的viewModel
- relaunch过程中保存旧Activity的viewModel
- reference
2022/08/21
Activity创立ViewModel
-
创立ViewModel
// MyActivity#onCreate() val mainViewModel = [V1] ViewModelProvider(this) [V2] .get(MainViewModel::class.java) -
[V1]ViewModelProvider结构函数
// androidx.lifecycle.ViewModelProvider#get(java.lang.Class<T>) public constructor( owner: ViewModelStoreOwner ) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))this指MyActivity,即MyActivity应该是
[I]ViewModelStoreOwner类型MyActivity承继
[C]ComponentActivity],ComponentActivity完成了[I]ViewModelStoreOwner接口// CompnentActivity public class ComponentActivity extends androidx.core.app.ComponentActivity implements // ... ViewModelStoreOwner, // ... {this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner)),这儿运用owner.viewModelStore从ViewModelStoreOwner中取出[OC]ViewModelStore]// ViewModelStoreOwner interface ViewModelStoreOwner { /** * The owned [ViewModelStore] */ val viewModelStore: ViewModelStore }然后调用下面的结构函数
// ViewModelStoreOwner /** * Creates a ViewModelProvider * * @param store `ViewModelStore` where ViewModels will be stored. * @param factory factory a `Factory` which will be used to instantiate new `ViewModels` * @param defaultCreationExtras extras to pass to a factory */ @JvmOverloads constructor( private val store: ViewModelStore, private val factory: Factory, private val defaultCreationExtras: CreationExtras = CreationExtras.Empty, ) { -
[V2]调用了get办法⬇️
// androidx.lifecycle.ViewModelProvider#get(java.lang.Class<T>) @MainThread public open operator fun <T : ViewModel> get(modelClass: Class<T>): T { val canonicalName = modelClass.canonicalName ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels") [W1] return get("$DEFAULT_KEY:$canonicalName", modelClass) } -
[W1]// androidx.lifecycle.ViewModelProvider#get(java.lang.String, java.lang.Class<T>) @MainThread public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T { [X1]val viewModel = store[key] [X1]if (modelClass.isInstance(viewModel)) { .... [X1] return viewModel as T .... [X2]return try { [X2] factory.create(modelClass, extras) [X2] catch (e: AbstractMethodError) { [X2] factory.create(modelClass) [X2]}.also { store.put(key, it) } } -
[X1]⬅️[W1]从store(
[OC]ViewModelStore)中能找到viewmodel则直接回来 -
[X2]⬅️[W1]store中找不到则需要新创立一个viewmodel并放入store,这儿说明只需运用同一个ViewModelStore获取ViewModel则不同当地获取到的都是同一个ViewModel
[OC]ViewModelStore看起来是个Map,事实上他的完成便是保护一个map,放出get和put办法open class ViewModelStore { private val map = mutableMapOf<String, ViewModel>() ... fun put(key: String, viewModel: ViewModel) { } operator fun get(key: String): ViewModel? { return map[key] } ... }
总结上面,Activity在onCreate时创立viewModel,Activity是一个ViewModelStoreOwner其间有一个ViewModelStore其间保护一个map,ViewModelProvier作为一个工具类在运用默许的/我们供给的Factory(为了适配结构函数有参的ViewModel)创立ViewModel的一起会将其存入这个map。
所以,在relaunch过程中,毁掉旧的Activity时假如能保存它的mViewModelStore,然后将其赋值新的Activity的mViewModelStore就能完成装备改变viewModel不改变的效果。
Activity重建ViewModel坚持存在的完成
relaunch之后新的Activity获取之前的viewModel
viewModel存在ViewModelStore中,说明ViewModelStore在Activity重建的过程中能坚持存在,看下[C]ComponentActivity怎么怎么获取[OC]ViewModelStore的
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.");
}
[T1] ensureViewModelStore();
return mViewModelStore;
}
-
[T1]在getViewModelStore()办法中调用了ensureViewModelStore()保证mViewModelStore不为空
@SuppressWarnings("WeakerAccess") /* synthetic access */ void ensureViewModelStore() { if (mViewModelStore == null) { [U1] NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null) { // Restore the ViewModelStore from NonConfigurationInstances [U2] mViewModelStore = nc.viewModelStore; } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } } } -
[U1]⬅️[T1]// Activity @Nullable public Object getLastNonConfigurationInstance() { return mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.activity : null; }Activirty.mLastNonConfigurationInstances类型为
[C]Activity.NonConfigurationInstances// android.app.Activity.NonConfigurationInstances static final class NonConfigurationInstances { Object activity; .... }mLastNonConfigurationInstances.activity在
[U1]⬅️[T1]处被强转为[C]ComponentActivity.NonConfigurationInstances// androidx.activity.ComponentActivity.NonConfigurationInstances static final class NonConfigurationInstances { Object custom; ViewModelStore viewModelStore; } -
[U2]⬅️[T1]假如
[U1]获取的nc不为空,则将mViewModelStore赋值为nc.viewModelStore 即Activity.mLastNonConfigurationInstances.activity.viewModelStore所以想要保存给新Activity运用本来的viewModel,重点便是要在relaunch过程中保存旧的Activity.mLastNonConfigurationInstances然后再赋值给新Activity.mLastNonConfigurationInstances
relaunch过程中保存旧Activity的viewModel
设备改变,系统调用AMS的updateConfiguration 办法
ActivityManagerService.java – Android Code Search
// ActivityManagerService
@Override
public boolean updateConfiguration(Configuration values) {
return mActivityTaskManager.updateConfiguration(values);
}
// ActivityTaskManagerService
@Override
public boolean updateConfiguration(Configuration values) {
....
updateConfigurationLocked(values, null, false, false /* persistent */,
....
}
// ActivityTaskManagerService
boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
boolean initLocale, boolean persistent, int userId, boolean deferResume,
ActivityTaskManagerService.UpdateConfigurationResult result) {
....
「I1」 changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId);
....
「I2」 kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
....
}
-
「I1」updateGlobalConfigurationLocked 更新当时装备信息
-
「I2」ensureConfigAndVisibilityAfterUpdate 保证给定的activity更新运用的装备
这儿starting传入的是null,需要ensureConfigAndVisibilityAfterUpdate中自己获取
// ActivityTaskManagerService boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) { boolean kept = true; 「J1」 final Task mainRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask(); .... 「J2」 starting = mainRootTask.topRunningActivity(); .... 「J3」 kept = starting.ensureActivityConfiguration(changes, .... } -
「J1」⬅️「I2」获取根窗口容器中当时具有焦点的尖端任务(root task)
-
「J2」⬅️「I2」获取尖端任务(root task)中当时正在运转的尖端Activity(top running Activity)的ActivityRecord赋值给starting
-
「J3」⬅️「I2」ActivityRecord对应的Activity更新Configuration
// com.android.server.wm.ActivityRecord#ensureActivityConfiguration(int, boolean) boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) { return ensureActivityConfiguration(globalChanges, preserveWindow, false /* ignoreVisibility */); }// com.android.server.wm.ActivityRecord#ensureActivityConfiguration(int, boolean, boolean) boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreVisibility) { .... relaunchActivityLocked(preserveWindow); .... }// com.android.server.wm.ActivityRecord#relaunchActivityLocked void relaunchActivityLocked(boolean preserveWindow) { .... 「K2」 final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, .... 「K1」 final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), token); 「K2」 transaction.addCallback(callbackItem); .... 「K3」 mAtmService.getLifecycleManager().scheduleTransaction(transaction); .... } -
「K1」⬅️「J3」token来自
[C]ActivityRecord承继的[C]WindowToken中的tokenclass WindowToken extends WindowContainer<WindowState> { private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM; /** The actual token */ final IBinder token; /** The type of window this token is for, as per {@link WindowManager.LayoutParams} */ final int windowType;// ClientTransaction /** Obtain an instance initialized with provided params. */ public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) { ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class); if (instance == null) { instance = new ClientTransaction(); } instance.mClient = client; instance.mActivityToken = activityToken; return instance; }将transaction.mActivityToken设置为ActivityRecord.token
-
「K2」⬅️「J3」给transaction放入callback:
[C]ActivityRelaunchItem -
「K3」⬅️「J3」履行transaction
// com.android.server.wm.ClientLifecycleManager#scheduleTransaction(ClientTransaction) void scheduleTransaction(ClientTransaction transaction) throws RemoteException { .... transaction.schedule(); .... }// ClientTransaction public void schedule() throws RemoteException { 「L1」 mClient.scheduleTransaction(this); } -
「L1」⬅️「K3」[C]ClientTransaction运用mClient履行自己- mClient是什么?
// ClientTransaction /** Target client. */ private IApplicationThread mClient;这儿是运用AIDL(根据Binder)进行进程间通信,对应文件
IApplicationThread.aidl⬇️oneway interface IApplicationThread { .... void scheduleTransaction(in ClientTransaction transaction);这儿mClient是客户端,对应的客户端为
[c]ApplicationThreadprivate class ApplicationThread extends IApplicationThread.Stub {
- mClient是什么?
-
「M1」⬅️「L1」所以下面从 android.app.ActivityThread.ApplicationThread#scheduleTransaction办法继续
// android.app.ActivityThread.ApplicationThread#scheduleTransaction @Override public void scheduleTransaction(ClientTransaction transaction) throws RemoteException { ActivityThread.this.scheduleTransaction(transaction); }这儿scheduleTransaction是调用的ActivityThread的基类ClientTransactonHandler中的scheduleTransaction办法
// android.app.ClientTransactionHandler#scheduleTransaction void scheduleTransaction(ClientTransaction transaction) { 「N1」 transaction.preExecute(this); 「N2」 sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); } -
「N1」⬅️「M1」为后面transaction的履行做些预备,这儿this传入的是
[C]ActivityThreadpublic void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) { if (mActivityCallbacks != null) { .... for (int i = 0; i < size; ++i) { 「O1」 mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken); .... } -
「O1」⬅️「N1」履行每个callback的preExecute办法,callback只有一个之前在
「K2」处放入的ActivityRelaunchItem// android.app.servertransaction.ActivityRelaunchItem#preExecute public void preExecute(ClientTransactionHandler client, IBinder token) { 「P1」 mActivityClientRecord = client.prepareRelaunchActivity(token, mPendingResults, mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow); } -
「P1」⬅️「O1」从ActivityThread(即client)获取要relaunch的ActivityRecord存入ActivityRelaunchItem.mActivityClientRecord
@Override public ActivityClientRecord prepareRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, int configChanges, MergedConfiguration config, boolean preserveWindow) { 「Q1」 .... 「Q2」 target = new ActivityClientRecord(); 「Q2」 target.token = token; .... 「Q3」 mRelaunchingActivities.add(target); .... return ....target....; } -
「Q1」⬅️「P1」检查是否方针activity是否现已正在relaunch了,假如是则回来
-
「Q2」⬅️「P1」方针activity没有现已正在relaunch(这儿认为是没有,这个判别只是为了避免relaunch正在relaunch的activity),则结构一个
[sC]ActivityClientRecord记录要relaunch的Activity的token等信息 -
「Q3」⬅️「P1」运用ActivityThread.mRelaunchingActivities记录一切要预备重启的ActivityClientRecord+-----------------------------------------------------+ | | | ActivityThread | | | | +-----------------------------------+ | | | mRelaunchingActivities | | | | | | | | +------------------------+ | | | | | ActivityClientRecord | | | | | +------------------------+ | | | | | | | | +------------------------+ | | | | | ActivityClientRecord | | | | | +------------------------+ | | | | | | | | .... | | | | | | | | | | | +-----------------------------------+ | | | +-----------------------------------------------------+ -
「N2」⬅️「M1」这儿运用Handler去真实履行transaction,obj传入的便是transaction
// android.app.ClientTransactionHandler#sendMessage abstract void sendMessage(int what, Object obj);// android.app.ActivityThread#sendMessage(int, java.lang.Object) void sendMessage(int what, Object obj) { sendMessage(what, obj, 0, 0, false); }⬇️结构Message
// android.app.ActivityThread#sendMessage(int, java.lang.Object, int, int, boolean) private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { .... msg.what = what; msg.obj = obj; .... mH.sendMessage(msg); }⬇️handler:ActivityThread.H 收到音讯并处理
// android.app.ActivityThread.H#handleMessage public void handleMessage(Message msg) { ... switch (msg.what) { ... case EXECUTE_TRANSACTION: 「R1」 final ClientTransaction transaction = (ClientTransaction) msg.obj; 「R2」 mTransactionExecutor.execute(transaction); .... -
「R1」⬅️「N2」从message中取出transaction -
「R2」⬅️「N2」交给mTransactionExecutor履行mTransactionHandler 是谁?是
[C]ActivityThread,从TransactionExecutor的结构函数⬇️中能够看出// ActivityThread private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);/** Initialize an instance with transaction handler, that will execute all requested actions. */ public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) { mTransactionHandler = clientTransactionHandler; }TransactionExecutor.mTransactionHandler是对持有该TransactionExecutor的ActivityThread的引证
+-------------------------------------------------------------------------------------+ | ActivityThread <-------+ | | | | | | | | +-----------------------------------------------------------------+ | | | mTransactionExecutor: TransactionExecutor | | | | | | | | | | | | | | | +-------------------------------------------------+---------+ | | | | | mTransactionHandler: ClientTransactionHandler | | | | | | | | | | | | | | | | | +-----------------------------------------------------------+ | | | | | | | | | | | +-----------------------------------------------------------------+ | | | +-------------------------------------------------------------------------------------+// android.app.servertransaction.TransactionExecutor#execute public void execute(ClientTransaction transaction) { .... executeCallbacks(transaction); .... }// android.app.servertransaction.TransactionExecutor#executeCallbacks public void executeCallbacks(ClientTransaction transaction) { final List<ClientTransactionItem> callbacks = transaction.getCallbacks(); .... 「S1」 final IBinder token = transaction.getActivityToken(); .... for (int i = 0; i < size; ++i) { final ClientTransactionItem item = callbacks.get(i); .... 「S2」 item.execute(mTransactionHandler, token, mPendingActions); .... } -
「S1」⬅️「R2」从transaction中获取activityToken
「K1」⬅️「J3」 -
「S2」⬅️「R2」callback(为ActivityRelaunchItem)履行,execute办法来自ActivityRelaunchItem 完成的接口BaseClientRequest的execute办法
至于mTransactionHandler是谁,在
「R2」现已解释execute办法来自ActivityRelaunchItem完成的接口BaseClientRequest中的execute办法⬇️
public interface BaseClientRequest extends ObjectPoolItem { .... void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions); .... }ActivityRelaunchItem和BaseClientRequest的关系⬇️
public abstract class ClientTransactionItem implements BaseClientRequestpublic abstract class ActivityTransactionItem extends ClientTransactionItempublic class ActivityRelaunchItem extends ActivityTransactionItemclassDiagram class ClientTransactionItem { } class ActivityTransactionItem { } class ActivityRelaunchItem { } class BaseClientRequest { <<interface>> + execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) } ClientTransactionItem <|-- ActivityTransactionItem ActivityTransactionItem <|-- ActivityRelaunchItem BaseClientRequest <|-- ClientTransactionItem: implements该execute办法由
[C]ActivityRelaunchItem的基类ActivityTransactionItem完成// ActivityTransactionItem public final void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { 「A1」 final ActivityClientRecord r = getActivityClientRecord(client, token); 「A2」 execute(client, r, pendingActions); } -
「A1」根据token获取ActivityClientRecord// ActivityTransactionItem @NonNull ActivityClientRecord getActivityClientRecord( @NonNull ClientTransactionHandler client, IBinder token) { final ActivityClientRecord r = client.getActivityClient(token); .... return r; }client是 TransactionExecutor.mTransactionHandler,也便是持有TransactionExecutor的ActivityThread
// ActivityThread @Override public ActivityClientRecord getActivityClient(IBinder token) { return mActivities.get(token); } -
「A2」继续履行 ⬇️// ActivityRelaunchItem @Override public void execute(ClientTransactionHandler client, ActivityClientRecord r, PendingTransactionActions pendingActions) { .... 「B1」 client.handleRelaunchActivity(mActivityClientRecord, pendingActions); } -
「B1」mActivityClientRecord从哪里来?之前「P1」⬅️「O1」// ActivityThread @Override public void handleRelaunchActivity(ActivityClientRecord tmp, PendingTransactionActions pendingActions) { ... 「C1」 ActivityClientRecord r = mActivities.get(tmp.token); ... 「C2」handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents, pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity"); ... } -
「C1」⬅️「B1」这儿从
mActivities中根据token获取[sC]ActivityClientRecord+----------------------------------------------------------------+ | ActivityThread | | | | | | +------------------------------------------------------+ | | | mActivities | | | | +--------------------------------------+ | | | | | +---------------+ | | | | | | | Activity | | | | | | | +---------------+ | | | | | | | | | | | | +-------------------------------+ | | | | | | | lastNonConfigurationInstances | | | | | | | +-------------------------------+ | | | | | | | | | | | +--------------------------------------+ | | | | +--------------------------------------+ | | | | | | | | | | | | | | | | +--------------------------------------+ | | | | +--------------------------------------+ | | | | | | | | | | | | | | | | +--------------------------------------+ | | | | | | | | ... | | | | | | | +------------------------------------------------------+ | +----------------------------------------------------------------+ -
「C2」⬅️「B1」传递r给
// ActivityThread private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents, PendingTransactionActions pendingActions, boolean startsNotResumed, Configuration overrideConfig, String reason) { ... 「D1」 handleDestroyActivity(r, false, configChanges, true, reason); ... 「D2」 handleLaunchActivity(r, pendingActions, customIntent); } -
「D1」⬅️「C2」⬇️Destroy本来的Activity,其间getNonConfigInstance传入了true
// ActivityThread @Override public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) { performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason); ... }⬇️将本来的activity的nonConfigurationInstances存入ActivityRecord.lastNonConfigurationInstances
// ActivityThread /** Core implementation of activity destroy call. */ void performDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) { ... 「E1」 if (getNonConfigInstance) { .... 「E2」 r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances(); .... -
「E1」这儿假如是getNonConfigInstance为true(前面传的是true), -
「E2」则️将
[sC]ActivityClientRecord中放入Java 代码块的成果,其间就包括viewModelStore// Activity NonConfigurationInstances retainNonConfigurationInstances() { 「F1」 Object activity = onRetainNonConfigurationInstance(); ... NonConfigurationInstances nci = new NonConfigurationInstances(); nci.activity = activity; .... return nci; } -
「F1」Activity默许完成中只回来了null,可是[C]ComponentActivity重写了这个办法⬇️// ComponentActivity public final Object onRetainNonConfigurationInstance() { // Maintain backward compatibility. 「G1」 Object custom = onRetainCustomNonConfigurationInstance(); ViewModelStore viewModelStore = mViewModelStore; 「G2」 if (viewModelStore == null) { .... } .... 「G3」 NonConfigurationInstances nci = new NonConfigurationInstances(); nci.custom = custom; nci.viewModelStore = viewModelStore; return nci; } -
「G1」我们能够经过重写onRetainCustomNonConfigurationInstance()创立custom即自定义的在configuration改变后仍然想要保存的数据。 -
「G2」这儿当viewModelStore为空的时分会检查[C]ComponentActivity.NonConfigurationInstances中是否有viewModelStore,这儿对应从来没有当地调用过getViewModelStore,也就不会初始化ComponentActivity.mVieModelStore,可是我们这儿状况是之前有创立viewmodel,this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner)),这儿运用owner.viewModelStore从ViewModelStoreOwner中取出[OC]ViewModelStore调用过,一切不会走到viewModelStore == null的分支 -
「G3」这儿创立了[C]ComponentActivity.NonConfigurationInstances存入 custom和viewModelStore并回来。 -
「D2」⬅️「C2」履行LaunchActivity// android.app.ActivityThread#handleLaunchActivity public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) { .... final Activity a = performLaunchActivity(r, customIntent); .... return a; }// android.app.ActivityThread#performLaunchActivity private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { .... Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); 「H1」 activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); .... try { .... if (activity != null) { .... 「H2」 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.activityConfigCallback, r.assistToken, r.shareableActivityToken); .... return activity; } -
「H1」实例化一个Activity
-
「H2」运用本来的ActivityRecord给Activity设置参数,其间第12个参数便是在
「E2」处保存的lastNonConfigurationInstances,其间就有viewModel这儿就回答了上面
[U2]处的问题,串起来了
reference
code
- Android 面试总结 – ViewModel 是怎么保存和康复? – ()
- Android Framework之Activity启动流程(一) | 柚子 | pomeloJiang
- Zygote的启动流程 – ()
- Android屏幕旋转源码探索及使用实践 | 奔哲明的博客 (benzblog.site)
- Configuration 改变时Activity的生命周期探求 – ()
