Android应用重启后语言未保留问题排查求助
问题排查与修复方案
你的代码核心问题在于语言设置时机太晚,以及过时的Locale配置方式,导致重启应用后无法正确恢复语言设置。以下是具体问题和修复步骤:
1. 语言设置时机错误
当前loadLocale()在setContentView()之后调用,此时Activity的界面已经初始化完成,语言配置的修改无法作用到已加载的布局资源上。必须在Activity创建的更早阶段设置Locale,也就是attachBaseContext()方法中。
2. 过时的Locale配置API
Android 7.0(API 24)之后,configuration.locale已被废弃,需要使用configuration.setLocale(locale)替代,同时对于RTL语言(如阿拉伯语、乌尔都语),还需设置布局方向以适配从右到左的排版。
3. 空字符串Locale的问题
选择English时传入空字符串"",new Locale("")会创建无效Locale,应该明确指定"en"作为默认英文标识。
完整修复代码
第一步:修改LoginActivity,调整语言设置时机
public class LoginActivity extends AppCompatActivity { private ActivityLoginBinding binding; @Override protected void attachBaseContext(Context newBase) { // 在Activity初始化前加载并应用语言设置 loadLocale(newBase); super.attachBaseContext(newBase); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityLoginBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); getSupportActionBar().setTitle(R.string.title_activity_login); binding.btnChangeLanguage.setOnClickListener(v -> changeLanguage()); } private void changeLanguage() { final String languages [] = {"عربي", "বাংলা", "English", "हिंदी", "اردو"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.choose_language); builder.setSingleChoiceItems(languages, -1, (dialog, which) -> { String langCode; switch (which) { case 0: langCode = "ar"; break; case 1: langCode = "bn"; break; case 2: langCode = "en"; break; // 替换空字符串为明确的en case 3: langCode = "hi"; break; case 4: langCode = "ur"; break; default: langCode = "en"; } setLocale(langCode); recreate(); dialog.dismiss(); // 选择后关闭对话框 }); builder.show(); } private void setLocale(String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration configuration = getResources().getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { configuration.setLocale(locale); configuration.setLayoutDirection(locale); // 适配RTL语言布局 } else { configuration.locale = locale; } getResources().updateConfiguration(configuration, getResources().getDisplayMetrics()); // 持久化保存语言设置 SharedPreferences.Editor editor = getSharedPreferences("Settings", MODE_PRIVATE).edit(); editor.putString("appLanguage", language); editor.apply(); Toast.makeText(this, "Language Changed", Toast.LENGTH_SHORT).show(); } private void loadLocale(Context context) { SharedPreferences preferences = context.getSharedPreferences("Settings", MODE_PRIVATE); String language = preferences.getString("appLanguage", "en"); // 默认语言设为英文 setLocaleForContext(context, language); } // 单独封装上下文语言设置逻辑,供attachBaseContext调用 private void setLocaleForContext(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration configuration = context.getResources().getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { configuration.setLocale(locale); configuration.setLayoutDirection(locale); } else { configuration.locale = locale; } context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); } }
第二步:(推荐)在Application类中统一处理语言
如果应用包含多个Activity,建议在Application的attachBaseContext中统一设置语言,避免每个Activity重复代码:
public class MyApplication extends Application { @Override protected void attachBaseContext(Context base) { loadLocale(base); super.attachBaseContext(base); } private void loadLocale(Context context) { SharedPreferences preferences = context.getSharedPreferences("Settings", MODE_PRIVATE); String language = preferences.getString("appLanguage", "en"); setLocaleForContext(context, language); } private void setLocaleForContext(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration configuration = context.getResources().getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { configuration.setLocale(locale); configuration.setLayoutDirection(locale); } else { configuration.locale = locale; } context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); } }
记得在AndroidManifest.xml中注册该Application:
<application android:name=".MyApplication" ...> ... </application>
关键修复点总结
- 将语言设置逻辑移到
attachBaseContext(),确保在资源加载前生效 - 使用API兼容方式设置Locale和布局方向,适配高版本系统
- 替换空字符串Locale为明确的
"en",避免无效Locale问题 - 可选:在Application级别统一处理语言,确保所有Activity重启后保持设置
内容的提问来源于stack exchange,提问作者Mehboob
相关产品推荐
相关产品推荐

