我有一个开始活动(A)和语言选择活动(B)。活动A具有语言指示,在单击时启动活动B.活动B具有语言列表视图,点击后在共享首选项中设置语言代码并启动活动A.活动A覆盖attachBaseContext
方法,读取语言首选项,用正确的语言环境包装上下文并将其返回。
但如果我尝试在KitKat(4.4)上多次更改语言,应用程序会因内存不足而崩溃。 Memory usage
工具显示每次语言更改时有10个上下文和数字增加(我猜这是崩溃的原因)。我如何找到上下文泄漏的问题?
方法如下。 从A到B:
//goto language selection activity
Intent selectLanguageIntent = new Intent(StartingActivity.this, LanguageSelectionActivity.class);
//disables going back to previous activity
selectLanguageIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(selectLanguageIntent);
finish();
从B到A:
//get language name from clicked item
String language = (String) adapterView.getItemAtPosition(i);
//get shared preferences
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences(getString(R.string.language_setting_preferences_file), Context.MODE_PRIVATE);
sharedPreferences.edit().putString("lang", language).apply();
//goto starting activity
Intent startingActivity = new Intent(LanguageSelectionActivity.this, StartingActivity.class);
//disables going back to previous activity
startingActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(startingActivity);
finish();
覆盖attachBaseContext
:
@Override
protected void attachBaseContext(Context newBase) {
//get shared preferences
SharedPreferences languageSettingPreferences = newBase.getSharedPreferences(newBase.getString(R.string.language_setting_preferences_file), Context.MODE_PRIVATE);
//read language stored in shared preferences
myLanguage = languageSettingPreferences.getString("lang", null);
//check if any language is stored
if (myLanguage != null) {
//if stored, wrap a context with stored locale
super.attachBaseContext(LangChangeContextWrapper.wrap(newBase, LangChangeContextWrapper.getLanguageCode(myLanguage)));
} else {
//if not stored, return the same context
super.attachBaseContext(newBase);
}
}
班级LangChangeContextWrapper
:
public class LangChangeContextWrapper extends ContextWrapper {
static Map<String, String> languageCodes;
//default constructor
public LangChangeContextWrapper(Context base) {
super(base);
}
//wraps a context with requested locale
public static ContextWrapper wrap(Context context, String language) {
Configuration config = context.getResources().getConfiguration();
Locale sysLocale;
sysLocale = getSystemLocale(config);
Locale locale = new Locale(language);
Locale.setDefault(locale);
setSystemLocale(config, locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
context = context.createConfigurationContext(config);
} else {
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
return new LangChangeContextWrapperNew(context);
}
//gets default system locale
public static Locale getSystemLocale(Configuration config) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return config.getLocales().get(0);
} else {
return Locale.getDefault();
}
}
//sets systems locale
public static void setSystemLocale(Configuration config, Locale locale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
} else {
config.locale = locale;
}
}
//returns language code for language name
public static String getLanguageCode(String language) {
//creates hashmap of languages
fillUpLanguageCodes();
return languageCodes.get(language);
}
//returns hashmap of languages
public static Map<String, String> getLanguageCodesMap() {
//creates hashmap of languages
fillUpLanguageCodes();
return languageCodes;
}
//creates hashmap of languages
public static void fillUpLanguageCodes() {
//only creates once
if (languageCodes == null) {
//map of supported languages
languageCodes = new LinkedHashMap<>();
languageCodes.put("English", "en");
languageCodes.put("Lietuviškai", "lt");
}
}