android开发:app实现中英文切换

最近做了个小项目,领导要求添加可以切换中英文的功能,自己实现了这么一个效果:
android开发:app实现中英文切换_第1张图片

这里说一下我的实现思路:

1.编写不同语言环境的string.xml文件
2.编写一个工具类修改程序的配置信息
3.销毁重建activity使配置生效
4.重建activity后根据在主线程中存储的语言标识修改按钮图标(右上角的按钮)

1.编写不同语言环境的string.xml文件
android studio生成不同语言环境的string.xml文件
参考:
Android studio 添加多语言支持

2.编写一个工具类修改程序的配置信息

package com.phyplusinc.android.phymeshprovisioner.utils;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.util.Locale;

/**
 * @Author: david.lvfujiang
 * @Date: 2019/12/11
 * @Describe:语言切换工具类
 */
public class LanguageUtil {
    //弱引用持有Context
    private static WeakReference<Context> weakReference;
    public static String settingLanguage(Context context, ThreadLocal threadLocal) {
        weakReference = new WeakReference<>(context);
        //获得res资源对象
        Resources resources = weakReference.get().getResources();
        //获得设置对象
        Configuration config = resources.getConfiguration();
        //获得屏幕参数:主要是分辨率,像素等。
        DisplayMetrics dm = resources.getDisplayMetrics();
        //使用ThreadLocal获取主线程的数据
        String language = (String) threadLocal.get();
        if ("English".equals(language)) {
            // 设置语言为中文
            config.locale = Locale.CHINESE;
            threadLocal.set("Chinese");
            Log.e("TAG", "Chinese");

        } else {
            //英语(美国)
            config.locale = Locale.US;
            threadLocal.set("English");
            Log.e("TAG", "English");
        }
        //修改配置
        resources.updateConfiguration(config, dm);
        return language;
    }

    //获取ThreadLocal对象
    public static ThreadLocal getInstance() {
        return Holder.threadLocal;
    }

    //在静态内部类实现的单例模式
    private static class Holder {
        private static ThreadLocal threadLocal = new ThreadLocal<String>();
    }

}



这个工具类主要的作用就是修改app的语言配置,这个过程需要context上下文,为了防止内存泄漏我使用了弱引用持有context。并且使用ThreadLocal单例对象(静态内部类实现单例模式)在主线程中存一个语言标识languageThreadLocal的源码与及应用场景可以参考我的这篇博客:android开发:ThreadLocal使用场景与源码解析

然后在activity中需要切换语言时就调用工具类修改配置,然后销毁重建activity配置才会生效

 @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.img_language:
            	//修改配置
                LanguageUtil.settingLanguage(MainActivity.this,LanguageUtil.getInstance());
                //activity銷毀重建
                MainActivity.this.recreate();
                break;
            default:
                break;
        }

activity銷毀重建会创建新的activity对象,系统会通过onSaveInstanceState()保存一些数据,activity重建时会回调onRestoreInstanceState()方法。因此我重写onRestoreInstanceState()在其中获取通过ThreadLocal获取主线程的语言标识来选择切换不同的图片。

 @Override
    public void onRestoreInstanceState(Bundle bundle){
        super.onRestoreInstanceState(bundle);
        Log.e("TAG","onRestoreInstanceState");
        activityReset();
    }
    
	  /**
     * activity銷毀重建后会执行这个方法
     */
    public void activityReset() {
    	//同一个对象在同一个线程中获取的数据是一样的,因为每个线程都维护了一个ThreadLocalMap对象,key值是ThreadLocal
        ThreadLocal<String> threadLocal = LanguageUtil.getInstance();
        String language = threadLocal.get();
        if ("English".equals(language)) {
            imgLanguage.setImageResource(R.mipmap.chinese);
        } else if ("Chinese".equals(language)) {
            imgLanguage.setImageResource(R.mipmap.english);
        }
     }

这个例子功能其实很简单,但是我考虑到的东西还挺多,单例模式、内存泄露、ThreadLocal等。因此在写代码的时候不要止单单实现功能而已,应该学会思考这样写有什么问题吗?有没有更好的写法?

你可能感兴趣的:(android开发基础)