Configuration(Android 6.0)

本文详细探讨了Android系统如何根据Configuration变化更新资源,特别是当语言变更时,为何需要重启Activity。通过分析设置语言的流程,揭示了Configuration在资源匹配、更新配置、清除缓存以及重启Activity等方面的作用,帮助理解Android系统的资源管理和配置更新机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说到Configuration,大家最熟悉的想必是android:configChanges=[“mcc”, “mnc”, “locale”,”touchscreen”, “keyboard”, “keyboardHidden”,”navigation”,”screenLayout”, “fontScale”, “uiMode”,”orientation”, “screenSize”, “smallestScreenSize”],而这个属性了解的最多的就是在横竖屏切换的”orientation”。
在Activity中定义android:configChanges=”orientation”,这样当横竖屏切换时,可以在onConfigurationChanged监听到改变,同时Activity不会被重启。不知道大家是否想过,为什么如果不定义orientation时,系统需要重启Activity呢?
这还要从资源说起,Android应用程序在资源的定义中,会为不同的屏幕尺寸,语言,横竖屏定义不同的资源文件,存放不同的资源。以保证应用程序可以适配不同的屏幕,语言,横竖屏等等。而Android系统如何从当前应用程序中获取最合适的资源来显示呢?
下面是官网给的Android系统从应用程序中获取资源的流程:官方链接
这里写图片描述
图中第二步:table中包含MCC, MNC, Language等18个资源获取的维度,table说的是资源配置表,有了这个资源配置表,Android系统就可以从aapt打包生成的resources.arsc中通过上面图标中的步骤,找到最合适的资源。而这个资源配置表,就是通过Configuration来设置的。
再回到系统为什么需要重启Activity的问题上,比如当Configuration中语言(local)发生变化时,也就是说当前获取最佳资源的维度发生了变化,也就是说在Configuration变化之前已经启动的Activity上显示的资源已经不是最合适当前配置的资源了,因此系统需要更新资源配置,清除之前配置缓存的资源,然后重启已经启动的Activity以便显示更新Configuration配置的资源。
接下来就以语言的变化流程,看系统是如何更新配置,清除缓存资源,然后重启已经启动的Activity。

1 Setting应用中更换语言时:调用LocalePicker.updateLocale

public static void updateLocale(Locale locale) {
IActivityManager am = ActivityManagerNative.getDefault();
Configuration config = am.getConfiguration();
config.setLocale(locale);
config.userSetLocale = true;
am.updateConfiguration(config);
}
这个函数主要获取AMS代理对象,然后从AMS中获取Configuration对象config,设置config中改变的对象locale也就是语言,并设置userSetLocale为true, 最有通过AMS的代理对象调用AMS的updateConfiguration函数。

2 AMS的updateConfiguration函数主要是调用updateConfigurationLocked()函数。
这个函数比较长,分三个部分来分析:
1 初始化和其他设置阶段:

boolean updateConfigurationLocked(Configuration values,
ActivityRecord starting, boolean persistent, boolean initLocale) {
int changes = 0;
if (values != null) {
Configuration newConfig = new Configuration(mConfiguration);
changes = newConfig.updateFrom(values);
if (changes != 0) {
if (!initLocale && values.locale != null && values.userSetLocale) {
final String languageTag = values.locale.toLanguageTag();
SystemProperties.set(“persist.sys.locale”, languageTag);
mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG, values.locale));
}
mConfigurationSeq++;
if (mConfigurationSeq <= 0) {
mConfigurationSeq = 1;
}
newConfig.seq = mConfigurationSeq;
mConfiguration = newConfig;
mUsageStatsService.reportConfigurationChange(newConfig, mCurrentUserId);

            if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
                Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
                msg.obj = new Configuration(configCopy);
                mHandler.sendMessage(msg);

A 创建newConfig = new Configuration(mConfiguration);
在Configuration构造函数中会调用setTo函数,把mConfiguration的各个成员变量赋值到newConfig中。
在Configuration的成员变量中,包含mcc(移动国家编码), mnc(移动网络编码), locale(语言),keyboardHidden(键盘显隐),等等,每一个都是一个资源获取的维度,每一个都影响当前应用中最合适资源的匹配。
同时在ActivityInfo中还定义了,CONFIG_MCC,CONFIG_MNC,CONFIG_LOCALE等静态整型变量,这些整型变量与Configuration的成员变量一一对应,并最终以位的形式标记,新旧Configuration哪些成员变量发生了变化。

B 调用Configuration. updateFrom通过改变的Configuration对象values更新newConfig,同时返回整数change,change就是以位的形式标记values和newConfig哪些成员变量发生了变化,在语言设置的流程中必然整数change的CONFIG_LOCALE位为”1”,标记当前语言发生了变化。

C 因为Configuration的local成员变量发生了变化,所以change不为0,接下来,
通过发送消息SEND_LOCALE_TO_MOUNT_DAEMON_MSG 设置local到MountService,
设置newConfig 的mConfigurationSeq
提交newConfig 到UsageStatsService(统计服务)
发送消息UPDATE_CONFIGURATION_MSG 把改变的Configuration 保存到设置中。
二部分:通知各个应用进程,Configuration改变:

mSystemThread.applyConfigurationToResources(configCopy);
for (int i=mLruProcesses.size()-1; i>=0; i–) {
ProcessRecord app = mLruProcesses.get(i);
try {
if (app.thread != null) {
app.thread.scheduleConfigurationChanged(configCopy);
}
} catch

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值