ToastUtils切換多語(yǔ)言無(wú)效

前言

公司項(xiàng)目的Toast統(tǒng)一用到com.blankj.utilcode.util.ToastUtils的工具類,由于公司項(xiàng)目是維護(hù)多語(yǔ)言的,所以在應(yīng)用內(nèi)有切換多語(yǔ)言的入口,但是應(yīng)用切換了多語(yǔ)言后,應(yīng)用的語(yǔ)言已經(jīng)變了,但Toast提示的語(yǔ)言并沒有變,嘗試了用系統(tǒng)的Toast卻是可以改變多語(yǔ)言的,但是項(xiàng)目很多地方用到了ToastUtils工具類,所以不能用系統(tǒng)的Toast來(lái)替換,所以就有了這篇探索文章了。

ToastUtils工具類的探索

這是一個(gè)大神編寫的工具了,這個(gè)工具類的好處就是不用傳入context,可以在很多沒有context對(duì)象的地方調(diào)用,當(dāng)然這個(gè)工具類也對(duì)系統(tǒng)的Toast做了很多的處理,提供了各種功能。具體有什么功能大家可以查看這個(gè)工具類,我們現(xiàn)在回歸到我們的問(wèn)題,ToastUtils切換多語(yǔ)言無(wú)效。

ToastUtils在應(yīng)用中可以很方便的調(diào)用,只需在代碼中寫上ToastUtils.showShort(R.string.bold_text);就可以了。

ToastUtils工具類的一些方法

但是為什么切換多語(yǔ)言就會(huì)沒效呢?

我們從這個(gè)類的源碼來(lái)分析探索一下


showShort方法,調(diào)用show方法傳入資源id和時(shí)間


show方法,從傳入資源id拿到字符串,在調(diào)用重載的show方法
重載的show方法,根據(jù)傳入的字符串,時(shí)間和拿到應(yīng)用的Context根據(jù)ToastFactoty工廠調(diào)用系統(tǒng)的Toast


根據(jù)反射獲取Application

從源碼中,我們可以知道ToastUtils不用傳入Context就可以Toast是因?yàn)楣ぞ哳愐呀?jīng)幫我們從反射中拿到了應(yīng)用的Application,所以我們不用傳入Context就可以調(diào)用Toast了,這就是ToastUtils工具類的方便之處。

但是切換多語(yǔ)言時(shí)為什么就不會(huì)切換資源呢?

多語(yǔ)言切換的探索

Android7.0及之后版本,使用了LocaleList,Configuration中的語(yǔ)言設(shè)置可能獲取的不同,而是生效于各自的Context。

* 這會(huì)導(dǎo)致:Android7.0使用舊的方式,有些Activity可能會(huì)顯示為手機(jī)的系統(tǒng)語(yǔ)言。

* Android7.0 優(yōu)化了對(duì)多語(yǔ)言的支持,廢棄了updateConfiguration()方法,替代方法:createConfigurationContext(), 而返回的是Context。

* 也就是語(yǔ)言需要植入到Context中,每個(gè)Context都植入一遍。


在繼承的Application類中覆寫這兩個(gè)方法,設(shè)置修改多語(yǔ)言
在繼承的BaseActivity類中覆寫這個(gè)方法修改activity的多語(yǔ)言


系統(tǒng)多語(yǔ)言的設(shè)置

我公司的應(yīng)用是兼用到5.0以上的,所以修改多語(yǔ)言就跑到此方法context = context.createConfigurationContext(config);所以重啟activity時(shí)就能更新多語(yǔ)言。但是我們的應(yīng)用是沒有重新啟動(dòng)的,所以Application是沒有更新的。從之前對(duì)ToastUtils的分析,ToastUtils是拿到應(yīng)用的Application當(dāng)做Context的,所以ToastUtils對(duì)于切換多語(yǔ)言就沒效了。從這分析,是Application沒有更新導(dǎo)致多語(yǔ)言沒效,于是就拿系統(tǒng)的Toast傳入application當(dāng)Context嘗試,果真也是無(wú)效的。

解決辦法

一.既然是Application沒有更新導(dǎo)致多語(yǔ)言無(wú)效,那我們就更新Application就可以了。但Application是應(yīng)用一啟動(dòng)就創(chuàng)建了,自始至終就是這個(gè),不會(huì)更新的,所以我們就得重啟應(yīng)用,殺掉這個(gè)進(jìn)程來(lái)更新這個(gè)Application。

1.?

Intent intent = new Intent(this, Object.class);

startActivity(intent);

System.exit(0);

finish();

2. 通過(guò)ActivityManager來(lái)重新啟動(dòng)應(yīng)用程序:

ActivityManager manager = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);

manager.restartPackage("com.example.test");

3. 通過(guò)flag來(lái)實(shí)現(xiàn):

private void restartApplication() {

??????? final Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());

??????? intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

??????? startActivity(intent);

}

4. 利用PendingIntent

Intent mStartActivity = new Intent(context, StartActivity.class);

int mPendingIntentId = 123456;

PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId,??? mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);

AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);

System.exit(0);

只有關(guān)閉進(jìn)程才算真正的更新了Application,所以只有1.4是有效的,但是這個(gè)更新Application的方式體驗(yàn)很不好,因?yàn)殛P(guān)閉進(jìn)程到重啟會(huì)出現(xiàn)黑屏。

二.從多語(yǔ)言的切換我們知道,切換多語(yǔ)言有兩種方法

1.context = context.createConfigurationContext(config);

2.resources.updateConfiguration(config, dm);

第二種方法Android7.0 優(yōu)化了對(duì)多語(yǔ)言的支持,廢棄了updateConfiguration()方法,替代方法:createConfigurationContext(), 而返回的是Context。也就是語(yǔ)言需要植入到Context中,每個(gè)Context都植入一遍。使用第二種方法會(huì)導(dǎo)致:Android7.0使用舊的方式,有些Activity可能會(huì)顯示為手機(jī)的系統(tǒng)語(yǔ)言。

但是我們可以在更新多語(yǔ)言的時(shí)候把應(yīng)用的application傳進(jìn)來(lái)更新應(yīng)用的application資源就可以了,而不需要替換application


更新application的多語(yǔ)言方法

ToastUtils切換多語(yǔ)言就可以了,應(yīng)用的Application也更新了資源。這種方法效果比一的方法好,對(duì)應(yīng)用沒有什么影響。


總結(jié)

經(jīng)過(guò)這次的bug的處理,讓我對(duì)源碼的學(xué)習(xí)更加深入,學(xué)會(huì)如何分析問(wèn)題,找到問(wèn)題和解決問(wèn)題。其中也學(xué)習(xí)了多語(yǔ)言的切換的,反射,應(yīng)用重啟還有各個(gè)Context的不同,雖然理解的可能還不是很深入,但是萬(wàn)丈高樓平地起,凡是都是從點(diǎn)滴積累的,以后繼續(xù)加油!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容