android開發:app實現中英文切換

最近做了個小項目,領導要求添加可以切換中英文的功能,自己實現了這麼一個效果:
在這裏插入圖片描述

這裏說一下我的實現思路:

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等。因此在寫代碼的時候不要止單單實現功能而已,應該學會思考這樣寫有什麼問題嗎?有沒有更好的寫法?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章