當前位置:編程學習大全網 - 源碼下載 - App多語言實現

App多語言實現

項目中遇到 切換app語言 的需求,要求在“簡體中文”和“English”兩種語言之間切換部分控件的語言文案,不受系統語言切換的影響。

TODO 切換系統Configuration設置源碼分析

TODO Android資源管理機制

按照Android的資源管理方式,我們需要在res目錄下建立兩個values目錄,其中values是默認的路徑,values-en是英文資源的目錄。

默認情況下,app啟動會根據系統的設置加載對應的資源,系統切換了語言設置,app也會更新設置,所以這樣不能完全滿足我們的需求。

我們不想要app隨著系統語言的改變而改變,而是保持用戶上壹次的選擇。默認安卓系統不會保留app的語言設置,我們需要本地記錄壹下用戶的選擇,在app重新啟動的時候加載之前保存的語言資源。存儲用戶的選擇比較容易,放到SharedPreference裏即可。然後在app重新啟動的時候,我們需要手動更新下app的Application、Activity、Fragment和Service收到的配置信息。

以Activity為例,我們在基類的attachBaseContext方法中更新保存有config信息的Context對象:

ConfigurationUtil.attachBaseContext(newBase) 方法中更新newBase對象,使其中保存的Locale為我們自定義,而非系統的。當Activity被attach到window時,調用到此方法,便會加載我們想要的資源。這時如果手動修改了系統語言設置,然後從任務歷史中切回我們的app時,棧中的所有Activity會被系統依照展示次序依次銷毀重建(棧頂被銷毀重建,退出到前壹個頁面時,前壹個頁面會被銷毀重建)。由於Activity被銷毀重建,會重新執行了生命周期方法,Activity的attachBaseContext方法也就會被重新執行到,所以系統的語言修改後,我們仍然可以正確地加載到我們自己設置的語言資源,所以從表面上看並沒有受到系統修改的影響。

通常官方也是建議我們重啟所有Activity的,這麽做會銷毀舊的資源數據,重新加載新的,安全方便。

官方描述:

如果我們不希望在系統語言發生變化時重啟Activity,需要在Manifest.xml文件中配置: android:configChanges="locale" 即可。

這樣做之後我們會在重新回到Activity的時候,進入回調方法 public void onConfigurationChanged(Configuration newConfig) {... 中去執行。其參數newConfig對象代表所有當前配置,而不僅僅是已經變更的配置。

需要註意:當我們修改系統語言設置後,系統會更新當前手機中所有正在運行的進程裏的所有組件(分析在開篇的鏈接裏有說明),所以這種情況下再次回到Activity,如果我們刷新UI,UI會使用系統的設置加載相應的資源文件。比如,

假設我們app設置為了簡體中文(我們在Application中保存相應的flag,來判斷系統的語言設置是否和app的設置壹致或者發生了變化),如果系統由簡體中文修改為了English,如果我們不做上述處理,刷新UI會加載英文資源。

這並不是我們想要的效果,所以我們需要在onConfigurationChanged回調中,再次更新Context中的Resources設置。做法如下:

上述方案並非完美結局問題,onConfigurationChanged方法調用之前getResource()有可能就會被調用多次,時序問題,加載出依據系統的語言設置的資源文件。(。>︿<)_θ,所以會有4的兜底方案。

TODO 切換語言並回到app,然後新建fragment並add,會有資源加載錯誤情況

我們在Activity的onConfigurationChanged方法更新過資源,貌似這裏沒有起作用。有種暴力的方式:

我們在 getResources() 方法中調用 ConfigurationUtil.updateResources(getResources()); ,但是 getResources() 方法會被多次調用,每次調用會判斷壹次,並不是特別理想,不過可以及時刷新,再未找到更好的方法前也算是壹種兜底的方案。

在切換的Activity中,我們最好重啟壹下所有的app,執行下方方法後,重新打開singleTask的MainActivity...

  • 上一篇:中小企業裝壹個ERP系統需要多少錢
  • 下一篇:電腦開不了機,出現藍屏還死機 錯誤代碼是0X0000007E 怎麽處理?
  • copyright 2024編程學習大全網