You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 07:12:08