Android应用内全局切换语言失效问题求助(Java实现)
Hey there! I see you're stuck getting your language switch to work across all activities—only MainActivity updates, right? Let's break down what's going wrong and fix it with Java code tailored to your setup.
Why Your Current Setup Only Works on MainActivity
The core issue is that other activities aren't loading the persisted language configuration when they initialize. Your LocaleHelper has the right foundational logic, but you're not hooking it into every activity's startup process. Plus, just calling recreate() on MainActivity doesn't ensure future activities use the new locale.
Step-by-Step Solution
1. Hook LocaleHelper into Every Activity
You need to override attachBaseContext in all your activities (or create a base Activity class that others extend) to apply the saved locale before the activity fully starts.
Add this method to every Activity in your app:
@Override protected void attachBaseContext(Context newBase) { // Apply the saved language configuration before the activity initializes super.attachBaseContext(LocaleHelper.onAttach(newBase)); }
This ensures every activity uses your persisted language instead of the system default when launching.
2. Update LocaleHelper for Android N+ (API 24+)
Your current updateResources method uses setLocale, which is deprecated in API 24+. Replace it with setLocales to ensure compatibility and proper locale application across newer Android versions:
Modified LocaleHelper class:
public class LocaleHelper{ private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; public static Context onAttach(Context context) { String lang = getPersistedData(context, Locale.getDefault().getLanguage()); return setLocale(context, lang); } public static Context onAttach(Context context, String defaultLanguage) { String lang = getPersistedData(context, defaultLanguage); return setLocale(context, lang); } public static String getLanguage(Context context) { return getPersistedData(context, Locale.getDefault().getLanguage()); } public static Context setLocale(Context context, String language) { persist(context, language); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return updateResources(context, language); } return updateResourcesLegacy(context, language); } private static String getPersistedData(Context context, String defaultLanguage) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); } private static void persist(Context context, String language) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor editor = preferences.edit(); editor.putString(SELECTED_LANGUAGE, language); editor.apply(); } @TargetApi(Build.VERSION_CODES.N) private static Context updateResources(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration configuration = context.getResources().getConfiguration(); // Replace deprecated setLocale with setLocales for API 24+ configuration.setLocales(new LocaleList(locale)); return context.createConfigurationContext(configuration); } @SuppressWarnings("deprecation") private static Context updateResourcesLegacy(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Resources resources = context.getResources(); Configuration configuration = resources.getConfiguration(); configuration.locale = locale; resources.updateConfiguration(configuration, resources.getDisplayMetrics()); return context; } }
3. Restart the App Properly After Language Change
Instead of just calling recreate() on MainActivity, restart the entire app to ensure all subsequent activities pick up the new locale. Modify your onPositiveClicked method:
@Override public void onPositiveClicked(String language) { // Apply the new locale to the app context LocaleHelper.setLocale(getApplicationContext(), language); // Restart the app to apply changes across all activities Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); }
This clears the existing activity stack and launches MainActivity fresh with the updated locale.
4. Clean Up Your Save Button Logic (Optional)
Instead of messy if-else blocks, use a map to map spinner items to language codes for cleaner, more maintainable code:
case R.id.savebutton: Map<String, String> languageMap = new HashMap<>(); languageMap.put(languageArray[0], "ko"); languageMap.put(languageArray[1], "en"); String selectedItem = languageSpinner.getSelectedItem().toString(); String targetLanguage = languageMap.get(selectedItem); if (targetLanguage != null) { customDialogListener.onPositiveClicked(targetLanguage); } dismiss(); break; case R.id.closebutton: cancel(); break;
How This Works
attachBaseContext: Ensures every activity loads the persisted language before it's created, so all screens use the correct locale from the start.- Updated
LocaleHelper: Fixes compatibility issues with newer Android versions and properly applies the locale to the app's configuration. - App Restart: Guarantees that even activities already in the stack are replaced with fresh instances using the new locale.
Give these changes a try—your language switch should now work seamlessly across all activities!
内容的提问来源于stack exchange,提问作者user12971295

