Android面试系列之应用内多语言切换
昨天组里的同事遇到一些切换多语言的细节问题,发现在Android N版本上配置应用内多语言没有生效,正好拿出来做为一个面试题讲解一下。
面试题:如何实现应用内多语言切换?
我们知道Android的多语言实现很简单,可以在不同的语言环境下使用不同的资源。在不同的res/value-xx下放置不同语言的strings.xml实现字符的本地化,而这个value-xx目录的选择是根据Resource中的Configuration.Locale这项的值来决定的。如zh中文,就会选择value-zh目录,如果没有匹配到(即APK中没有value-zh目录)就使用默认的value目录中的字符资源。
其实最终实现字符串的选择都是在Assets这个类中,通过Native的方法来加载相应的字符串资源。
然而,我们还是会有一些业务场景需要不根据Android系统的Locale配置就改变应用的语言。实现的方式也很简单,直接调用Android开放的接口Resources.updateConfiguration:
public static void changeSystemLanguage(Context context, String language) {
if (context == null || TextUtils.isEmpty(language)) {
return;
}
Resources resources = context.getResources();
Configuration config = resources.getConfiguration();
if (Locale.SIMPLIFIED_CHINESE.getLanguage().equals(language)) {
config.locale = Locale.SIMPLIFIED_CHINESE;
} else {
config.locale = new Locale(language);
}
resources.updateConfiguration(config, null);
}
上面的代码,我们可以在应用内通过language的值指定是显示哪种语言,当然language值我们需要保存在Preferences或者数据库中。
好像很简单,我们的项目为什么还会出现问题呢?而且大家都不知道如何下手,因为在Android N之前的版本都是可以正常切换语言的。后来我跟了一下,发现在MainActivity和SplashActivity这些Activity有继承了自已扩展的BaseActivity,而这个BaseActivity有这样一段代码:
@Override
public Resources getResources() {
Resources res = super.getResources();
Configuration config = new Configuration();
config.setToDefaults();
res.updateConfiguration(config, res.getDisplayMetrics());
return res;
}
config.setToDefaults会将Locale的值设为null,而再调用updateConfiguration可能会根据Android系统的语言重新设置Resources中的Locale。好吧,只是假设,还没有看到Android N的源代码。不过去掉这段代码后,在Android N(Preview)手机上切换语言正常了。
小结
今天遇到的问题,是以前遗留的代码埋下的坑终于暴露出来,也是这个项目缺乏代码审查(Code Review)机制的结果。找了几个人也无法说清覆写getResources这个方法的用意,最终也只能按历史问题处理了,是历史总有一些说不清楚的事,对吧。
回到这个面试题,现在你知道了可以在应用内切换语言(当然也可以修改Configuration的其他值),那么你有没有想过,如果不知道这个updateConfiguration的存在,你会怎么实现这个需求呢?或者说没有人和你说过updateConfiguration,你能找到它吗?
- python 函数编程的位置参数、默认参数、关键字参数以及函数的递归
- Java子类的父类和要实现的接口有相同的方法/函数会冲突吗
- Java关键字 Finally执行与break, continue, return等关键字的关系
- #if 和#ifdef的区别
- python高阶函数:map(f,[list]),reduce(f,[list],可选初始值),
- 深入探讨 Java 类加载器
- 斐波那契查找原理详解与实现
- 增量数据丢失的原因分析(二)(r8笔记第76天)
- pycharm 之模块与模块引用
- 判断栈的出栈顺序合法性
- Combination Sum II 组合数求和之2-Leetcode
- Combination Sum 组合数求和-Leetcode
- python 中输出字符的颜色控制属性
- 一则数据库无法重启的案例分析(r8笔记第96天)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- [- Flutter基础篇 -] 聊聊那些弹框
- 聊一聊Android中的StateListAnimator
- Linux KeyLogger
- [- Flutter 数据&状态篇 -] InheritedWidget
- Android实现图片一边的三角形边框效果
- Android使用SoundPool播放短音效
- 用Jquery做一个进度条
- Android SoundPool实现简短小音效
- [-Flutter趣玩篇-] 出神入化的Align
- Android应用禁止屏幕休眠的3种方法
- Flutter 实现下拉刷新上拉加载的示例代码
- [- C++趣玩篇1 -] 从打印开始说起
- Android实现蓝牙(BlueTooth)设备检测连接
- JQuery 入门学习(三)
- Android实现美团APP的底部滑动菜单