Android应用程序上下文配置不支持';t将使用新的区域设置进行更新
当我没有在Android应用程序上下文配置不支持';t将使用新的区域设置进行更新,android,locale,Android,Locale,当我没有在ViewModel中使用Context相关类(活动、片段、服务、视图等)或保留所有业务逻辑的自定义构建类时,我需要访问应用程序的本地化字符串。例如,在LiveData的帮助下,将字符串发布到UI: toastMessageLiveData.value = buildLastLoginToastMessage() fun buildLastLoginToastMessage() { val lastLoginDiff = (System.currentMillis() - get
ViewModel
中使用Context
相关类(活动、片段、服务、视图等)或保留所有业务逻辑的自定义构建类时,我需要访问应用程序的本地化字符串。例如,在LiveData
的帮助下,将字符串发布到UI
:
toastMessageLiveData.value = buildLastLoginToastMessage()
fun buildLastLoginToastMessage() {
val lastLoginDiff = (System.currentMillis() - getLastLogin()) / DateUtils.HOURS_IN_MILLIS
return MyApp.instance.getString(R.string.last_login_txt, lastLoginDiff)
}
现在在活动中
我正在观察LiveData
的变化,并显示一条Toast消息
这很好,但是如果用户更改应用程序的语言,问题就会出现。布局已更新,我可以看到使用了新区域设置的语言,但MyApp.instance.getString(R.string…)
函数仍在使用旧区域设置。如果我强制关闭应用程序并重新启动它,它会工作,因为应用程序的attachBaseContext
会再次调用,并应用新的区域设置。但是,我不想强制杀死应用程序,我需要一个解决方案来更新应用程序的配置
用于创建或更新上下文的实用程序函数
fun buildLocalizedContext(context: Context): Context {
// From preferences, load the saved Language and Country codes
val language = getSavedLanguage()
val country = getSavedCountry()
// Create the new locale
val locale = Locale(language, country)
Locale.setDefault(locale)
val resources = context.resources
val configuration = Configuration(resources.configuration)
// Create a new configration or update the existing one if the API is less than 17
if (Build.VERSION.SDK_INT >= 17) {
configuration.setLocale(locale)
return context.createConfigurationContext(configuration)
} else {
configuration.locale = locale
resources.updateConfiguration(configuration, resources.getDisplayMetrics())
}
return context
}
应用程序启动时,应用新的区域设置
class MyApp: Application {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleHelper.instance.buildLocalizedContext(base))
}
}
其他活动正在使用的BaseActivity
类:
class BaseActivity: AppCompatActivity {
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.instance.buildLocalizedContext(newBase))
}
}
到目前为止,我已经做到了这一点,但这也不起作用:
fun changeLocale(locale: Locale, app: Application) {
Locale.setDefault(locale)
val resources = app.resources
val configuration = resources.configuration
if (Build.VERSION.SDK_INT >= 17) {
configuration.setLocale(locale)
}
else {
configuration.locale = locale
resources.updateConfiguration(configuration, resources.displayMetrics)
}
}
上面的代码片段不起作用,只有在我强制重新启动应用程序时,它才会更改应用程序的区域设置。“这很好,但如果用户更改应用程序的语言,问题就会出现”——应用程序实际上没有语言。您的setLocale()
方法一直都有点像黑客,Android中的支持参差不齐。也就是说,是否有一种解决方案涉及您不直接访问应用程序,而是通过一些ContextWrapper
,您可以更改ContextWrapper
?@Commons使用的区域设置-一个解决方案是将字符串资源ID发送到Live Data
,并从活动
或片段
中获取字符串,但这通过将业务逻辑移动到UI来打破MVVM原则。在上面的示例中,您可以看到计算上次登录并生成字符串的业务逻辑是在ViewModel
中创建的。调用ViewModel
中的MyApp.instance.getString(R.string….)
函数时会出现问题,因为只有在我重新启动应用程序时,MyApp.instance.configuration.Locale
中的Locale
才会使用新的区域设置进行更新。我的观点是,与其调用MyApp.instance.getString()
,不如使用MyApp.instance
以外的其他方法(例如MyApp.instance
周围的ContextWrapper
)这仍然是全局范围,但可以在运行时替换。或者,字符串可能是通过调用函数创建的,调用方提供了活动
@commonware-感谢您的快速回复。如果您能给我一个示例,我如何使用或包装ContextWrapper
围绕MyApp.instance
或如何使用我是否可以从ViewModel
访问活动
,而不破坏MVVM
原则。对于后者,fun buildLastLoginToastMessage(ctxt:Context)
在您上面的代码片段中,该函数由您的活动或片段调用并在活动中传递,您使用ctxt
进行getString()
调用。对于前者,我只是建议您自己进行研究。就我个人而言,我永远不会编写使用setLocale()
的应用程序。