Android设备切换系统模式时导致Activity重建

当Android设备切换深色模式浅色模式时(通常指系统主题的切换),这种变化会影响应用程序的UI外观,包括背景颜色、文字颜色等。当用户更改系统主题时,系统会通知所有正在运行的应用程序来适应这个新的主题。

对于应用程序来说如果它没有显示的处理主题变更的情况,系统会默认重建Activity来实现这一变更。这是因为主题的变化可能会影响到Activity布局文件中定义的颜色或其他资源。为了确保这些资源的正确加载,系统选择了比较保险的方式——重建Activity。

解决方法:在AndroidManifest.xml文件中,为一个Activity指定android:configChanges="uiMode",意味着告诉系统,这个Acticvity能够处理uiMode的变化,而不应该简单的销毁重建。

当添加了android:configChanges="uiMode"后,系统将不会简单的销毁重建Activity来响应UI模式(如模式切换)系统将调用Activity的onConfigruationChanged(Configuration newConfig)方法,在方法中你可以处理与UI模式相关的任何更改,比如更新UI的颜色方案。

在AndroidManifest.xml中指定configChanges属性的示例

1 <activity android:name=".YourActivity"
2    android:configChanges="orientation|screenSize|uiMode" >
3    ...
4 </activity>

orientation|screenSize|uiMode中的|符号表示“或”关系,意味着这个Activity能够处理屏幕方向、屏幕大小和UI模式的变化。

然后,在Activity中重写onConfigurationChanged方法来处理这些配置变化:

1 @Override
2 public void onConfigurationChanged(Configuration newConfig) {
3    super.onConfigurationChanged(newConfig);
4
5    // 检查UI模式是否发生了变化
6    if (newConfig.uiMode != getResources().getConfiguration().uiMode) {
7        // 处理UI模式的变化,例如更新颜色主题等
8        updateTheme(newConfig.uiMode);
9    }
10 }
11
12 private void updateTheme(int mode) {
13    // 根据mode更新UI
14    if (mode == Configuration.UI_MODE_NIGHT_YES) {
15        // 夜间模式开启
16    } else if (mode == Configuration.UI_MODE_NIGHT_NO) {
17        // 夜间模式关闭
18    }
19    // 更新UI
20 }

需要注意的是,这种方法要求你在onConfigurationChanged方法中正确处理所有的配置变化,否则可能会导致UI显示不一致或者其他问题。如果你的应用依赖于某些特定的配置,或者配置变化会导致复杂的UI调整,那么确保你在onConfigurationChanged方法中实现了这些逻辑是非常重要的。

另外,从Android 4.4(API级别19)开始,Google建议使用Activity的recreate()方法来手动重建Activity,以确保Activity的生命周期被正确执行。如果你在onConfigurationChanged中无法处理好所有的配置变化,或者发现处理起来过于复杂,可以考虑在这个方法中调用recreate()来手动重建Activity。但是这样做的话,实际上还是会导致Activity的重建。因此,是否使用recreate()取决于你的具体需求和处理复杂性的能力。

当Android设备上的主题切换时,系统会进行一系列的操作来确保应用程序能够适配新的主题设置。以下是系统在主题切换时所做的主要工作:

1.检测主题变更:
当用户在系统设置中更改了主题(如切换到深色模式或浅色模式),系统会检测到这一变更。
2.广播通知:
系统会发送一个配置变更的广播,通知所有正在运行的应用程序当前的配置已经改变。这可以通过注册一个BroadcastReceiver来监听,但是更常见的是通过Activity生命周期中的onConfigurationChanged方法来响应。
3.配置变更处理:
对于那些声明了能够处理uiMode变更的Activity(即在AndroidManifest.xml中设置了android:configChanges="uiMode"),系统不会直接销毁Activity,而是调用其onConfigurationChanged方法。开发者需要在这个方法中实现相应的逻辑来更新UI。
4.Activity重建:
对于那些没有声明能够处理uiMode变更的Activity,默认行为是销毁当前Activity实例,并重新创建一个新的实例来适应新的配置。这意味着Activity的生命周期将从头开始,从onCreate方法开始执行。
在Activity重建之前,系统会调用onSaveInstanceState方法来保存Activity的状态,以便在重建后恢复。
5.资源加载:
系统会根据新的主题加载不同的资源文件,如颜色、样式和布局文件。这意味着应用程序中引用的颜色、字体和布局可能会根据主题的不同而有所变化。
6.通知UI组件更新:
对于应用程序内部的UI组件,如TextView、Button等,它们可能会根据新的主题更新其外观。例如,文本颜色、背景颜色等属性可能会根据新的主题设置进行更新。
7.应用级主题更新:
如果应用程序有全局主题设置,系统会通知应用程序更新其全局主题。这可能涉及到更新应用程序级别的样式和颜色。
8.Fragment更新:
如果Activity中有多个Fragment,那么每个Fragment也需要处理配置变更。这可能包括更新UI元素的颜色、字体等属性。


为了更好地处理主题切换,通常需要:

在Activity中重写onConfigurationChanged方法来处理配置变更。
使用onSaveInstanceState方法保存关键状态,以防止在Activity重建时丢失数据。
使用AppCompat库提供的组件,这些组件通常已经内置了对不同主题的支持。
监听Configuration对象的变化,尤其是uiMode字段,以便在需要的时候动态更新UI。
通过正确处理这些变更,可以确保应用程序在用户切换主题时依然能提供良好的用户体验。

1.colorMode - 表示颜色模式的变化,例如暗黑模式(dark mode)和亮色模式(light mode)之间的切换。
2.density - 表示屏幕密度的变化,例如从高密度(hdpi)到低密度(ldpi)的变化。
3.fontScale - 表示字体缩放比例的变化,例如用户改变了全局字体大小设置。
4.fontWeightAdjustment - 字体重粗度调整,可能指的是用户选择了更粗或更细的字体样式。
5.grammaticalGender - 语法性别变化,可能与某些语言的词形变化有关。
6.keyboard - 键盘类型的变化,例如全键盘、数字键盘或其他特殊键盘。
7.keyboardHidden - 键盘显示状态的变化,例如键盘弹出或隐藏。
8.layoutDirection - 布局方向的变化,例如从左到右(LTR)到从右到左(RTL)的变化。
9.locale - 语言环境的变化,例如从英语切换到中文。
10.mcc - 移动国家码(Mobile Country Code)的变化,可能与网络运营商有关。
11.mnc - 移动网络代码(Mobile Network Code)。
12.navigation - 导航硬件的变化,例如从虚拟导航栏变为物理按键或反之。
13.orientation - 屏幕方向的变化,例如从纵向变为横向。
14.screenLayout - 屏幕布局的变化,可能涉及屏幕尺寸和方向。
15.screenSize - 屏幕尺寸的变化,例如从大屏幕变为小屏幕。
16.smallestScreenSize - 最小屏幕尺寸的变化,例如由于键盘弹出导致的可用屏幕尺寸减小。
17.touchscreen - 触摸屏类型的变化,例如从电容式变为电阻式。
18.uiMode - 用户界面模式的变化,例如夜间模式(night mode)和白天模式(day mode)的变化。

处理配置变更  |  Android Developers (google.cn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值