要理解 res
/res-night
自动切换无需监听 onConfigurationChanged
的底层逻辑,需从 Android 资源系统设计、Configuration 配置管理、Activity 生命周期调度 三个核心维度拆解。以下是分层解析、生命周期分析及完整时序图。
一、核心原理概述
res-night
是 Android 为 UI 夜间模式 设计的 资源限定符目录 ,其自动切换的本质是:
当系统 日夜模式(UI Mode)变化 时,Android 系统会触发 全局 Configuration 配置更新 ,并对未声明 "自主处理 UI Mode 变化" 的 Activity 执行 销毁 - 重建流程 ;在重建过程中,系统会根据新的 Configuration 自动匹配 res-night
(夜间)或 res
(日间)资源,无需 App 手动监听。
关键前提:未在 AndroidManifest 中为 Activity 声明 android:configChanges="uiMode"
。若声明,则系统会跳过销毁重建,需 App 手动在 onConfigurationChanged
中处理资源切换。
二、Activity 生命周期是否重走?
默认会完整重走销毁 - 重建流程,这是资源自动切换的核心保障。具体生命周期调用顺序如下:
阶段 | 生命周期方法调用顺序(旧 Activity 销毁) | 生命周期方法调用顺序(新 Activity 重建) |
---|---|---|
1. 状态保存 | onSaveInstanceState(Bundle outState) |
- |
2. 暂停与停止 | onPause() → onStop() |
- |
3. 销毁旧实例 | onDestroy() |
- |
4. 创建新实例 | - | onCreate(Bundle savedInstanceState) |
5. 恢复与显示 | - | onStart() → onRestoreInstanceState(Bundle) → onResume() |
说明:
onRestoreInstanceState
仅在onSaveInstanceState
保存了数据时调用(如屏幕旋转、日夜模式切换),用于恢复页面状态(如输入框内容、列表滚动位置)。
三、底层实现关键机制拆解
res
/res-night
自动切换的核心是 "系统配置变化 → AMS 调度 Activity 重建 → 资源系统加载匹配资源" 的闭环,需拆解为 5 个关键步骤:
1. 资源限定符与 Configuration 的映射
Android 资源系统通过 资源限定符 (如 night
、land
、hdpi
)匹配当前设备状态,其中:
-
res-night
对应Configuration.uiMode
字段的UI_MODE_NIGHT_YES
(夜间模式); -
res
(无night
限定符)对应Configuration.uiMode
的UI_MODE_NIGHT_NO
(日间模式)。
Configuration
是 Android 全局维护的 "设备状态配置类",包含 UI 模式、屏幕方向、语言等所有影响资源匹配的参数。
2. 系统配置变化的触发与传递
当用户在系统设置切换日夜模式时,触发以下流程:
-
触发源 :
SystemServer
中的UiModeManagerService
(UMS)------ 负责管理系统 UI 模式(日夜、车载等)。 -
核心操作:
- UMS 检测到模式切换(如用户点击 "夜间模式"),更新 系统全局 Configuration 的
uiMode
字段; - UMS 通过
ActivityManagerService
(AMS)的updateConfiguration()
接口,通知 AMS "全局配置已变化"。
- UMS 检测到模式切换(如用户点击 "夜间模式"),更新 系统全局 Configuration 的
3. AMS 的 Activity 配置变化决策
AMS 是 Activity 生命周期的 "总指挥",收到配置变化通知后会执行以下判断:
-
AMS 遍历当前所有运行的 Activity(通过
ActivityStack
管理); -
检查每个 Activity 的
AndroidManifest
中android:configChanges
是否包含uiMode
:- 未包含(默认情况) :AMS 判定该 Activity 无法自主处理 UI Mode 变化,触发 销毁 - 重建流程;
- 已包含 :AMS 跳过销毁重建,直接调用 Activity 的
onConfigurationChanged(Configuration newConfig)
,需 App 手动处理资源切换。
4. Activity 重建与 Resources 重建
Activity 销毁后,重建过程的核心是 创建与新 Configuration 匹配的 Resources 对象:
-
Context 与 Resources 的绑定 :每个 Activity 持有
ContextImpl
实例(Context 的具体实现),ContextImpl
通过ResourcesManager
获取Resources
对象; -
Resources 重建逻辑:
- AMS 调用
ActivityThread
创建新的 Activity 实例时,会传入更新后的全局 Configuration; ContextImpl
向ResourcesManager
请求新的Resources
;ResourcesManager
根据新 Configuration,通过AssetManager
加载匹配的资源目录(res-night
或res
);AssetManager
是资源加载的 "底层执行者",负责解析res-night
目录下的layout
、drawable
、color
等资源文件,并生成资源 ID 映射。
- AMS 调用
5. 视图重绘与 UI 自动更新
Activity 重建时,setContentView(R.layout.xxx)
会重新执行:
- 系统通过新的
Resources
对象解析布局文件,加载res-night
中的资源(如夜间主题色、深色图片); - 视图系统(
ViewRootImpl
)根据新资源执行measure
→layout
→draw
流程; - 最终屏幕显示切换后的 UI,完成自动切换。
四、完整调用时序图
以下使用 Mermaid 时序图 可视化整个流程,涉及角色包括:用户、SystemServer(UMS)、AMS、Activity、ContextImpl、ResourcesManager、AssetManager。

五、关键补充说明
-
Resources 缓存机制 :
ResourcesManager
会缓存不同Configuration
对应的Resources
对象,避免重复创建(如多次切换日夜模式时,直接复用已缓存的res-night
资源); -
强制不重建的场景 :若在
AndroidManifest
中声明android:configChanges="uiMode"
,则 AMS 会跳过销毁重建,直接调用onConfigurationChanged
,此时需 App 手动重建视图(如recreate()
或重新加载布局),否则资源不会更新; -
应用内切换日夜模式 :若 App 自行实现日夜模式(不依赖系统设置),需通过
AppCompatDelegate.setDefaultNightMode()
触发uiMode
变化,后续流程与系统切换一致,仍会触发 Activity 重建。
综上,res
/res-night
的自动切换是 Android 系统 "配置驱动资源加载、生命周期联动重建" 设计的体现,无需手动监听的核心是 系统代劳了配置判断与 Activity 重建。