前言
从切换白天和黑夜模式说起
一个场景是页面有倒计时功能,并实时显示时钟和倒计时剩余分钟数提醒
此时切换白天和黑夜模式导致页面生命周期重走,数据全部重置,问题出现
实际测试发现切换白天/黑夜模式,切换系统语言均会导致生命周期重走。
那么有哪些场景会导致页面生命周期重走?
配置项更改导致重建Activity
activity重建的细节
- Activity 重建过程中,先将原来的Activity 进行销毁(从onPause > onStop > onDestroy > onCreate 的生命周期)。
- 虽然是不同的Activity 对象,但重建时使用的ActivityClientRecord 却是相同的,而ActivityClientRecord 最终是被ActivityThread 持有,它是全局的。这也是onSaveInstanceState/onRestoreInstanceState 能够存储与恢复数据的本质原因。
activity重建的原因分析
- 系统内存不足
- 配置项改变(configuration change )
例如横竖屏切换,白天黑夜模式切换 - 调用activity的onCreate()方法
配置项声明不重建activity
横竖屏切换
<activity android:name="" android:configChanges="orientation|screenSize"></activity>
白天/黑夜模式
<activity android:name="" android:configChanges="uiMode"></activity>
系统语言切换
<activity android:name="" android:configChanges="locale|layoutDirection|keyboard"></activity>
解法探究
- UI自动跟随系统切换,保存和恢复数据,使用onSaveInstanceState保存数据或状态,onRestoreInstanceState恢复页面状态
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Logger.i(TAG, "onSaveInstanceState outState... ");
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Logger.i(TAG, "onRestoreInstanceState... ");
}
- 数据不变,重绘UI,声明配置项,页面不会重走,UI在onConfigurationChanged回调刷新即可
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Logger.i(TAG, "onConfigurationChanged... ");
int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
// Night mode is not active, we're using the light theme
break;
case Configuration.UI_MODE_NIGHT_YES:
// Night mode is active, we're using dark theme
break;
}
}