我正在开发一款应用程序,可以让您在本地更改语言。
为了使这项工作无需重新启动应用程序,我在 BaseActivity 上使用 ContextWrapper,其中我将语言分配给上下文:
override fun attachBaseContext(newBase: Context{
super.attachBaseContext(ContextWrapper(newBase.setAppLocale(Session.getLanguage())))
}
要更改语言,我使用了 setLocale 旧版和 ApplicationDelegate:
遗产
fun setLocale(lang: String) {
val myLocale = Locale(lang.toString())
Locale.setDefault(myLocale)
val res = resources
val dm = res.displayMetrics
val conf = res.configuration
conf.locale = myLocale
res.updateConfiguration(conf, dm)
}
新API SDK 33
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags(it)
AppCompatDelegate.setApplicationLocales(appLocale)
他们都做几乎相同的事情。第二个更有效,因为它本身重新创建布局。
问题是我使用的 ViewModel 架构实现了 RESOURCES Wrapper,以便在 ViewModel 内获取某些类型的资源,而不会泄漏上下文。团队并没有使用错误的东西。
包装如下:
class ResourceManager(val context: Context) {
fun getColor(@ColorRes resId: Int): Int = ContextCompat.getColor(getContextWrapped(), resId)
fun getString(@StringRes resId: Int): String = getContextWrapped().getString(resId)
fun getDrawable(@DrawableRes resId: Int): Drawable? = getContextWrapped().getDrawable(resId)
private fun getContextWrapped(): Context {
return ContextWrapper(context.setAppLocale(Session.getLanguage()))
}
}
真正的问题是什么? 问题是这个 ResourceManager 使用一个 CONTEXT,当更改语言时,这个 CONTEXT 仍然保留以前的 LANGUAGE 资源。也就是说,如果应用程序以英语启动并且我将其更改为意大利语,则 ResourceManager 将保留英语。
我找到的解决方案是像之前使用 Dagger 那样重新启动 HILT,这会生成一个新组件并清理旧组件。但是,对于 HILT,我不知道如何实现这一目标。如何覆盖单例资源并创建新资源。
你找到解决办法了吗?我也在寻找解决方案