覆盖 ContextWrapper 后资源不会在轮换后更新
Resources are not updated after rotation when overriding the ContextWrapper
在我的 Android 应用程序中,我有一个屏幕根据以下规则将多个项目显示到 RecyclerView
中:
- 屏幕在同一行纵向显示 3 个项目;
- 屏幕在同一行横向显示 4 个项目。
为了让系统根据设备方向选择正确的值(3或4),我将值存储到资源文件夹中:
<integer name="videos_recycler_span">3</integer>
被放入values-sw600dp
<integer name="videos_recycler_span">4</integer>
被放入values-sw600dp-land
我还覆盖了 Activity
的 attachBaseContext
方法,因为我想独立于设备的语言来管理应用程序的语言。
这里是方法:
override fun attachBaseContext(newBase: Context)
{
val appCountry = DataContainer.INSTANCE.getUICountry(newBase)
val appLang = DataContainer.INSTANCE.getUILang(newBase)
val appLocale = Locale(appLang, appCountry)
val wrapped = LangContextWrapper.wrap(newBase, appLocale)
super.attachBaseContext(wrapped)
}
这里是 LangContextWrapper
class :
class LangContextWrapper(base: Context)
: ContextWrapper(base)
{
companion object
{
fun wrap(context: Context, newLocale: Locale): ContextWrapper
{
val res = context.resources
val configuration = res.configuration
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
configuration.setLocale(newLocale)
val localeList = LocaleList(newLocale)
LocaleList.setDefault(localeList)
configuration.locales = localeList
}
else
{
configuration.setLocale(newLocale)
val dm = res.displayMetrics
res.updateConfiguration(configuration, dm)
}
configuration.setLayoutDirection(newLocale)
return ContextWrapper(context.createConfigurationContext(configuration))
}
}
}
然后从我的片段中,我使用 resources.getInteger(R.integer.videos_recycler_span)
检索所需的值。
如果我在 启动屏幕之前 改变方向,它会完美地工作,但在至少 2 个设备上,资源是我留在屏幕上并进行旋转。
设备是:
- Android7.1.1
上的平板电脑三星 SM-T550
- 平板电脑三星 SM-T285 Android 5.1.1
我没有其他物理平板电脑来进行测试,但我不会在模拟器上重现该问题。
如果我不覆盖 attachBaseContext
,它会再次起作用。
所以我想我的 LangContextWrapper
class 在某些三星设备上有问题?有人可以知道这是什么问题以及如何解决它吗?
根据我的测试,这是 Android 的问题。我可以在带有 API 24 的模拟器上重现该问题。但不能在带有 API 28.
的模拟器上重现
在我的 Android 应用程序中,我有一个屏幕根据以下规则将多个项目显示到 RecyclerView
中:
- 屏幕在同一行纵向显示 3 个项目;
- 屏幕在同一行横向显示 4 个项目。
为了让系统根据设备方向选择正确的值(3或4),我将值存储到资源文件夹中:
<integer name="videos_recycler_span">3</integer>
被放入values-sw600dp
<integer name="videos_recycler_span">4</integer>
被放入values-sw600dp-land
我还覆盖了 Activity
的 attachBaseContext
方法,因为我想独立于设备的语言来管理应用程序的语言。
这里是方法:
override fun attachBaseContext(newBase: Context)
{
val appCountry = DataContainer.INSTANCE.getUICountry(newBase)
val appLang = DataContainer.INSTANCE.getUILang(newBase)
val appLocale = Locale(appLang, appCountry)
val wrapped = LangContextWrapper.wrap(newBase, appLocale)
super.attachBaseContext(wrapped)
}
这里是 LangContextWrapper
class :
class LangContextWrapper(base: Context)
: ContextWrapper(base)
{
companion object
{
fun wrap(context: Context, newLocale: Locale): ContextWrapper
{
val res = context.resources
val configuration = res.configuration
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
configuration.setLocale(newLocale)
val localeList = LocaleList(newLocale)
LocaleList.setDefault(localeList)
configuration.locales = localeList
}
else
{
configuration.setLocale(newLocale)
val dm = res.displayMetrics
res.updateConfiguration(configuration, dm)
}
configuration.setLayoutDirection(newLocale)
return ContextWrapper(context.createConfigurationContext(configuration))
}
}
}
然后从我的片段中,我使用 resources.getInteger(R.integer.videos_recycler_span)
检索所需的值。
如果我在 启动屏幕之前 改变方向,它会完美地工作,但在至少 2 个设备上,资源是我留在屏幕上并进行旋转。
设备是:
- Android7.1.1 上的平板电脑三星 SM-T550
- 平板电脑三星 SM-T285 Android 5.1.1
我没有其他物理平板电脑来进行测试,但我不会在模拟器上重现该问题。
如果我不覆盖 attachBaseContext
,它会再次起作用。
所以我想我的 LangContextWrapper
class 在某些三星设备上有问题?有人可以知道这是什么问题以及如何解决它吗?
根据我的测试,这是 Android 的问题。我可以在带有 API 24 的模拟器上重现该问题。但不能在带有 API 28.
的模拟器上重现