为什么ViewModel对象不会因为屏幕旋转而重建

Android会在Activity执行销毁的生命周期之前,会将所有你想保存的数据放到NonConfigurationInstances对象里面, 然后会将ActivityNonConfigurationInstance对象放进ActivityClientRecord里面, 我们知道启动一个Activity会为他创建一个ActivityClientRecord对象,这个对象只会有一个,你现在是旋转屏幕,这个不涉及ActivityClientRecord对象的重新创建,所以你保存在里面的旧数据就会一直在.

1
2
3
4
5
6
7
8
9
class ActivityThread{
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason){
//将Activity创建的NonConfigurationInstance赋值给ActivityClentRecord
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();

}

}

现在看下Activity.retainNonConfigurationInstances()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Activity{

NonConfigurationInstances retainNonConfigurationInstances() {

// 需要保存自己的数据,就需要重写 onRetainNonConfigurationInstance 方法
Object activity = onRetainNonConfigurationInstance();


HashMap<String, Object> children = onRetainNonConfigurationChildInstances();


NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;

return nci;
}
}

然后ComponentActivity重写了onRetainNonConfigurationInstance方法:

1
2
3
4
5
6
7
8
9
10
11
12
class ComponentActivity{
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();

ViewModelStore viewModelStore = mViewModelStore;

NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
}

可以看到在ComponentActivity重写了onRetainNonConfigurationInstance方法,将ActivityViewModeStore放进了NonConfigurationInstance里面.

上面是关于viewModelStore存的操作,下面看下是怎么取的.


取的阶段发生在Activityattach阶段:

1
2
3
4
5
6
7
8
9
10
class ActivityThread{
private Activity performLaunchActivity(ActivityClientRecord r,Intent customInstent){
//可以看到在attach阶段,将activityClientRecord.lastNonConfigurationInstance值传了进去
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, r.shareableActivityToken))
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
class Activity{
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,
IBinder shareableActivityToken){
//对nonConfigurationInstance进行了赋值
mLastNonConfigurationInstances = lastNonConfigurationInstances;
}
}