前言
公司項目的Toast統(tǒng)一用到com.blankj.utilcode.util.ToastUtils的工具類,由于公司項目是維護多語言的系宜,所以在應用內有切換多語言的入口,但是應用切換了多語言后发魄,應用的語言已經變了盹牧,但Toast提示的語言并沒有變,嘗試了用系統(tǒng)的Toast卻是可以改變多語言的励幼,但是項目很多地方用到了ToastUtils工具類汰寓,所以不能用系統(tǒng)的Toast來替換,所以就有了這篇探索文章了苹粟。
ToastUtils工具類的探索
這是一個大神編寫的工具了有滑,這個工具類的好處就是不用傳入context,可以在很多沒有context對象的地方調用嵌削,當然這個工具類也對系統(tǒng)的Toast做了很多的處理毛好,提供了各種功能。具體有什么功能大家可以查看這個工具類苛秕,我們現(xiàn)在回歸到我們的問題肌访,ToastUtils切換多語言無效。
ToastUtils在應用中可以很方便的調用艇劫,只需在代碼中寫上ToastUtils.showShort(R.string.bold_text);就可以了吼驶。
但是為什么切換多語言就會沒效呢?
我們從這個類的源碼來分析探索一下
從源碼中轨帜,我們可以知道ToastUtils不用傳入Context就可以Toast是因為工具類已經幫我們從反射中拿到了應用的Application,所以我們不用傳入Context就可以調用Toast了魄咕,這就是ToastUtils工具類的方便之處衩椒。
但是切換多語言時為什么就不會切換資源呢?
多語言切換的探索
Android7.0及之后版本,使用了LocaleList毛萌,Configuration中的語言設置可能獲取的不同苟弛,而是生效于各自的Context。
* 這會導致:Android7.0使用舊的方式阁将,有些Activity可能會顯示為手機的系統(tǒng)語言膏秫。
* Android7.0 優(yōu)化了對多語言的支持,廢棄了updateConfiguration()方法做盅,替代方法:createConfigurationContext(), 而返回的是Context缤削。
* 也就是語言需要植入到Context中,每個Context都植入一遍吹榴。
我公司的應用是兼用到5.0以上的,所以修改多語言就跑到此方法context = context.createConfigurationContext(config);所以重啟activity時就能更新多語言图筹。但是我們的應用是沒有重新啟動的帅刀,所以Application是沒有更新的。從之前對ToastUtils的分析远剩,ToastUtils是拿到應用的Application當做Context的扣溺,所以ToastUtils對于切換多語言就沒效了。從這分析瓜晤,是Application沒有更新導致多語言沒效锥余,于是就拿系統(tǒng)的Toast傳入application當Context嘗試,果真也是無效的痢掠。
解決辦法
一.既然是Application沒有更新導致多語言無效哈恰,那我們就更新Application就可以了。但Application是應用一啟動就創(chuàng)建了志群,自始至終就是這個着绷,不會更新的,所以我們就得重啟應用锌云,殺掉這個進程來更新這個Application荠医。
1.?
Intent intent = new Intent(this, Object.class);
startActivity(intent);
System.exit(0);
finish();
2. 通過ActivityManager來重新啟動應用程序:
ActivityManager manager = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
manager.restartPackage("com.example.test");
3. 通過flag來實現(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);
只有關閉進程才算真正的更新了Application,所以只有1.4是有效的,但是這個更新Application的方式體驗很不好桑涎,因為關閉進程到重啟會出現(xiàn)黑屏彬向。
二.從多語言的切換我們知道,切換多語言有兩種方法
1.context = context.createConfigurationContext(config);
2.resources.updateConfiguration(config, dm);
第二種方法Android7.0 優(yōu)化了對多語言的支持攻冷,廢棄了updateConfiguration()方法娃胆,替代方法:createConfigurationContext(), 而返回的是Context。也就是語言需要植入到Context中等曼,每個Context都植入一遍里烦。使用第二種方法會導致:Android7.0使用舊的方式凿蒜,有些Activity可能會顯示為手機的系統(tǒng)語言。
但是我們可以在更新多語言的時候把應用的application傳進來更新應用的application資源就可以了胁黑,而不需要替換application
ToastUtils切換多語言就可以了废封,應用的Application也更新了資源。這種方法效果比一的方法好丧蘸,對應用沒有什么影響漂洋。
總結
經過這次的bug的處理,讓我對源碼的學習更加深入力喷,學會如何分析問題刽漂,找到問題和解決問題。其中也學習了多語言的切換的弟孟,反射爽冕,應用重啟還有各個Context的不同,雖然理解的可能還不是很深入披蕉,但是萬丈高樓平地起颈畸,凡是都是從點滴積累的,以后繼續(xù)加油没讲!