当我不在保留所有业务逻辑的自定义构建类中使用Context相关类(活动、片段、服务、视图等)时,我需要访问应用程序的本地化字符串ViewModel。例如,在 a的帮助下将 a发布String到:UILiveData
toastMessageLiveData.value = buildLastLoginToastMessage()
fun buildLastLoginToastMessage() {
val lastLoginDiff = (System.currentMillis() - getLastLogin()) / DateUtils.HOURS_IN_MILLIS
return MyApp.instance.getString(R.string.last_login_txt, lastLoginDiff)
}
Run Code Online (Sandbox Code Playgroud)
现在,Activity我正在观察LiveData的变化,并显示 Toast 消息。
这工作正常,但如果用户更改应用程序的语言就会出现问题。布局已更新,我可以看到使用了新语言环境的语言,但该MyApp.instance.getString(R.string....)功能仍在使用旧语言环境。如果我强制终止应用程序并重新启动它,它会工作,因为attachBaseContext再次调用应用程序并应用新的语言环境。但是,我不想强制终止应用程序,我需要一个解决方案来更新应用程序的配置。
用于创建或更新 Context
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
}
Run Code Online (Sandbox Code Playgroud)
当应用程序启动时,应用新的语言环境
class MyApp: Application {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleHelper.instance.buildLocalizedContext(base))
}
}
Run Code Online (Sandbox Code Playgroud)
BaseActivity其他活动正在使用的类:
class BaseActivity: AppCompatActivity {
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.instance.buildLocalizedContext(newBase))
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这是我设法做到的,但这也不起作用:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码片段不起作用,它不会更改应用程序的区域设置,仅当我强制重新启动应用程序时。
小智 2
正如您所经历的,语言和其他一些配置仅应用于视图上下文,而不是应用程序上下文。你的处境似乎很奇怪。您可能需要重新审视您的架构。通常,您希望获取视图中的字符串并将其传递给 ViewModel 进行处理。但是,如果您想让它按原样工作,也许您可以将 WeakReference 存储到应用程序对象内的视图,并使用它来获取本地化字符串。您还可以保留对视图的硬引用,但是您必须确保清除它以避免内存泄漏。最好的解决方案是修改您的架构,但这也是一个不错的解决方案。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
(application as App).activity = WeakReference<Activity>(this)
}
}
class App : Application {
var activity : WeakReference<Activity>? = null
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1484 次 |
| 最近记录: |