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()
的应用程序。