起因:
项目中适配了中英文语言,在切换英文语言重启软件后,部分已适配多语言的文字显示中文,在同一个Activity中有的正常,有的却不正常。
探究:
一开始以为哪里设置文字的时候没有去适配,于是开始整个项目搜素还是没找到,心中一万个草**跑过,于是乎来到百度搜索,果然有人遇到类似的问题,然后开始慢慢探究...
起初是在Application中 写了一个Toast 弹出一段从资源文件定义的文字,当软件语言设置为英文后,重启后弹出的确是中文,而在进入到主界面后默认是英文,而部分文字后续更新后也是中文,真是见了鬼了,两部分调用的都是同一个方法啊:
public final String getString(@StringRes int resId) {
return getResources().getString(resId);
}
难道 getResources() 不是同一个对象?于是我就在Application 中 和 Activity中打印了两个getResources()的hashcode:
确实不一样,然后又在这两个地方验证了Local信息,调用代码如下:
public static Locale getAppLocale(Context context) {
//获取应用语言
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
Locale locale = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = configuration.getLocales().get(0);
Log.i("App-TAG", "getAppLocale: " + locale.getLanguage() + " " + locale.getCountry());
} else {
locale = configuration.locale;
}
return locale;
}
输出:
小黑子,露出鸡脚了吧,竟然获取的默认Local不一致!
看来调用系统接口返回的也不一定准确啊,那么有什么好的解决方法吗?
解决:
既然系统接口获取的不准确,那就找到一个获取准确Local的方法就行了
Locale appLocale = new Locale("en")
使用该方式可以获取具体语言准确的Local,当然我们不能硬编码,可以在你切换语言的时候将 getLanguage() 持久化一下,在用的时候从缓存中拿就可以了。
为了确保万无一失,在Application 和 BaseActivity中 重写 attachBaseContext 方法,在方法中都要设置一下:
Application 和 BaseActivity中:
@Override
protected void attachBaseContext(Context base) {
Log.i("TAG", "attachBaseContext");
super.attachBaseContext(MultiLanguageUtil.attachBaseContext(base));
}
MultiLanguageUtil 类相关代码:
public static Context attachBaseContext(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return createConfigurationResources(context);
} else {
setConfiguration(context);
return context;
}
}
@TargetApi(Build.VERSION_CODES.N)
private static Context createConfigurationResources(Context context) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
//如果本地有语言信息,以本地为主,如果本地没有使用默认Locale
Locale locale = null;
String spLanguage = SpUtil.getString(context, ConstantGlobal.LOCALE_LANGUAGE);
String spCountry = SpUtil.getString(context, ConstantGlobal.LOCALE_COUNTRY);
Locale appLocale = new Locale(spLanguage);//getAppLocale(context);
if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {
if (isSameLocal(appLocale, spLanguage, spCountry)) {
locale = appLocale;
} else {
locale = new Locale(spLanguage, spCountry);
}
} else {
locale = appLocale;
}
configuration.setLocale(locale);
configuration.setLocales(new LocaleList(locale));
return context.createConfigurationContext(configuration);
}
public static void setConfiguration(Context context) {
Locale appLocale = getAppLocale(context);
//如果本地有语言信息,以本地为主,如果本地没有使用默认Locale
Locale locale = null;
String spLanguage = SpUtil.getString(context, ConstantGlobal.LOCALE_LANGUAGE);
String spCountry = SpUtil.getString(context, ConstantGlobal.LOCALE_COUNTRY);
if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {
if (isSameLocal(appLocale, spLanguage, spCountry)) {
locale = appLocale;
} else {
locale = new Locale(spLanguage, spCountry);
}
} else {
locale = appLocale;
}
Configuration configuration = context.getResources().getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLocale(locale);
} else {
configuration.locale = locale;
}
Resources resources = context.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
resources.updateConfiguration(configuration, dm);//语言更换生效的代码!
}
标签:spLanguage,中英文,locale,Locale,切换,context,appLocale,Android,configuration
From: https://blog.51cto.com/xaye/11999516