抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

createConfigurationContext误区

偶尔看到不常见的东西,需要做一下整理,加深印象。

此文大部分内容来自Drakeet在 扔物线 星球的分享

在关于createConfigurationContext的使用上,我的以为居然和Drakeet保持了一致,我一直认为:只要给这个方法一个 Configuration 对象,那么它就会返回一个 Context 包含我们给它的 Configuration 对象

然而并不是这样的。createConfigurationContext 的文档中写的是:

@param overrideConfiguration A {@link Configuration} specifying what values to modify in the base Configuration of the original Context’s resources. If the base configuration changes (such as due to an orientation change), the resources of this context will also change except for those that have been explicitly overridden with a value here.

翻译:指定要在原始 Context Configuration 修改的值。 如果原始 Configuration 发生了变更(例如由于屏幕方向更改),则此 Context 的 resources 也将更改,但那些已在此处用值明确覆盖的资源将保持不变。

关键就是其中的“specifying what values to modify in the base Configuration”——明确指定要修改的值(value/field)而不是替换掉整个原始 Configuration 对象,而且这些值将不会随着系统或环境变化而变化!

简单点说就是:createConfigurationContext内部会去探测我们传入的 Configuration 对象身上被明确设置的值,而且 Configuration 身上的值会有缺省状态(undefined),所以它能探测到我们明确设置了哪些值,这些明确设置的值将覆盖掉原有 Context 身上的 Configuration,并在后续保持不变(不因系统变化)。

所以我曾经这么写是完全错误的:

val config = Configuration(context.resources.configuration)
config.setLocale(locale)
return context.createConfigurationContext(config)

错误的地方在于 Configuration(context.resources.configuration),这么写相当于我们把原始 Configuration 的值全都复制过来,并且传递给 createConfigurationContext 后,它将会把所有值(field)全部覆盖掉,并且保持不变。而上面代码的原始目的其实很明确,我仅仅只是想修改 Locale 这个值(field),但结果是,导致 Configuration 所有值都被覆盖。

这么说可能有点不够直白,我们可以直接对比正确的写法,正确的写法应该是:

val config = Configuration()
config.setLocale(locale)
return context.createConfigurationContext(config)

使用一个全新的 Configuration() 这样才是对的,如此的话就真的只有 Locale 会被修改和固定住。

后来官方给了一个例子:androidx NightModeCustomApplyOverrideConfigurationActivity.java

防止有人看不到,附图一张:

刚看下了之前项目的写法,果然是错的~


0条评论

发表评论