Android 8.0应用语言切换异常问题求助
Android 8.0应用语言切换问题解决方案
我一看你这情况就知道是Android 7.0+系统里语言切换的典型坑——旧的配置更新API已经失效,再加上Context初始化时机和Activity重启方式不对,才导致切换时Toolbar没同步、杀进程后又变回英文。我给你梳理下问题根源,再直接上可运行的修复代码:
问题拆解
- 废弃API拖后腿:Android N(7.0)之后,
resources.updateConfiguration()被标记为废弃,直接调用根本没法保证配置在所有组件里生效。 - Application初始化时机错了:在
onCreate()里设置语言太晚,Application的Context已经初始化完了,后续启动的组件还是会用默认配置,杀进程重启自然就还原了。 - Activity重启方式不合理:用
finish() + startActivity(intent)重启Activity,容易因为栈的问题导致配置没重新加载,比如Toolbar这类系统控件就没同步更新。
修复步骤
1. 重构Application类,在正确时机初始化语言
我们得在attachBaseContext()里设置语言,这是Application Context创建的最早阶段,能确保所有后续组件都继承正确的语言配置:
class MyApplication : Application() { companion object { // 封装语言更新方法,返回更新后的Context fun updateLanguage(context: Context, lang: String): Context { val targetLocale = Locale(lang) Locale.setDefault(targetLocale) val resources = context.resources val config = resources.configuration.apply { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // Android N及以上用setLocales替代旧的setLocale setLocale(targetLocale) setLocales(LocaleList(targetLocale)) } else { @Suppress("DEPRECATION") setLocale(targetLocale) } } return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // Android N+用createConfigurationContext生成新的配置Context context.createConfigurationContext(config) } else { // 低版本仍使用updateConfiguration @Suppress("DEPRECATION") resources.updateConfiguration(config, resources.displayMetrics) context } } } override fun attachBaseContext(base: Context?) { // 先读取保存的语言设置,再初始化Context val sharedPref = PreferenceManager.getDefaultSharedPreferences(base) val savedLang = sharedPref.getString("lang", "en") ?: "en" // 更新Context后再传给父类,确保后续组件用的都是新配置 super.attachBaseContext(base?.let { updateLanguage(it, savedLang) }) } override fun onCreate() { super.onCreate() // 这里不再需要设置语言,attachBaseContext已经处理完毕 } }
2. 修改MainActivity的语言切换逻辑
用recreate()替代旧的重启方式,确保Activity完全重建并加载新配置;同时在切换时立即更新当前Activity的配置:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val sharedPref = PreferenceManager.getDefaultSharedPreferences(this) val currentLang = sharedPref.getString("lang", "en") ?: "en" // 每次onCreate都同步按钮和Toolbar文字,确保语言生效 switchLanguage.setText(if (currentLang == "en") R.string.english else R.string.viet) switchLanguage.isChecked = currentLang != "en" switchLanguage.setOnCheckedChangeListener { _, isChecked -> val targetLang = if (!isChecked) "en" else "vi" // 保存语言设置到SharedPreferences sharedPref.edit().putString("lang", targetLang).apply() // 更新当前Activity配置并重建,确保所有控件同步语言 val updatedContext = MyApplication.updateLanguage(this, targetLang) applyOverrideConfiguration(updatedContext.resources.configuration) recreate() } } }
关键修改说明
- attachBaseContext初始化:保证Application的Context从一开始就用指定语言,杀进程重启后不会还原为系统默认语言。
- 适配Android N+API:用
createConfigurationContext和setLocales替代废弃API,确保配置在所有组件中生效。 - Activity重建方式:
recreate()会触发Activity完整生命周期重建,包括Toolbar在内的所有控件都会重新加载当前语言的资源。
这样修改后,你应该就能解决切换时Toolbar不同步、杀进程后还原的问题了。
内容的提问来源于stack exchange,提问作者Hoang Duc Tuan
相关产品推荐
相关产品推荐

