Toast弹不出来之谜
前言
今天早上測(cè)試應(yīng)用的時(shí)候,忽然發(fā)現(xiàn)Toast彈不出來(lái)了,我用的華為測(cè)試機(jī),以為是通知權(quán)限被關(guān)了,后來(lái)發(fā)現(xiàn)是開(kāi)著的,這就納了悶了,這個(gè)Toast工具類(lèi)用了好長(zhǎng)時(shí)間了,后來(lái)發(fā)現(xiàn)這Toast原來(lái)還能這樣...
正文
以前工具類(lèi)是這個(gè)樣子的(華為的通知權(quán)限放在了其他的地方)
final public class ToastUtil {private static Toast toast;//單例的toast/*** 顯示Toast*/public static void showToast(int text) {showToast(App.getInstance().getResources().getString(text));}public static void showToast(String text) {if (toast == null)toast = Toast.makeText(App.getInstance(), text, Toast.LENGTH_SHORT);toast.setText(text);toast.show();} }平時(shí)用的都是好好的,為什么不能用了呢?
然后我通過(guò)debug發(fā)現(xiàn)所有路徑都走了,說(shuō)明是調(diào)用成功了,后來(lái)想起來(lái),是不是子線程的問(wèn)題,打印了一下線程信息:
Thread.currentThread().getName();發(fā)現(xiàn)果然第一次調(diào)用沒(méi)有跑在主線程中,這就尷尬了,在子線程中創(chuàng)建,并show()竟然沒(méi)有報(bào)錯(cuò),而且子線程創(chuàng)建的在主線程調(diào)用show()也沒(méi)有報(bào)錯(cuò),只是不顯示
到show()的源碼中發(fā)現(xiàn),被try了..
/*** Show the view for the specified duration.*/public void show() {if (mNextView == null) {throw new RuntimeException("setView must have been called");}INotificationManager service = getService();String pkg = mContext.getOpPackageName();TN tn = mTN;tn.mNextView = mNextView;try {service.enqueueToast(pkg, tn, mDuration);} catch (RemoteException e) {// Empty}}修改方法
在創(chuàng)建和show的時(shí)候可以判斷是否是主線程,如果不是就放到主線程中就ok了
修改后的代碼,嗯,這樣就可以了(雖然有強(qiáng)迫癥看到這代碼很不爽,但是首先得能用)
final public class ToastUtil {private static Toast toast;//單例的toast/*** 顯示Toast*/public static void showToast(int text) {showToast(App.getInstance().getResources().getString(text));}public static void showToast(final String text) {if (toast == null) {//AppManager.getAppManager().currentActivity()是使用工具類(lèi)獲取當(dāng)前Activity對(duì)象的方法AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {toast = Toast.makeText(App.getInstance(), text, Toast.LENGTH_SHORT);toast.show();}});} else {//如果show()是在子線程觸發(fā)的,則在主線程來(lái)顯示if ("main".equals(Thread.currentThread().getName())) {toast.setText(text);//將文本設(shè)置給toasttoast.show();} else {AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {toast.setText(text);//將文本設(shè)置給toasttoast.show();}});}}} }ps:近些天看到了一個(gè)類(lèi)似的情況,比我分析的源碼更多:懷疑人生,主線程修改UI也會(huì)崩潰?
擴(kuò)展
如果你因?yàn)槟承┣闆r,真的要在某個(gè)(注意是某個(gè))子線程中彈出toast,可以使用以下方法在子線程開(kāi)一個(gè)loop,這樣就可以彈toast了(當(dāng)然你要自己知道后果,具體百度):
thread {Looper.prepare()Toast.makeText(context, "123", Toast.LENGTH_LONG).show()Looper.loop()}如果遇到了連續(xù)彈toast后,導(dǎo)致后續(xù)一段時(shí)間彈不出toast,可以使用以下方法?,效果看起來(lái)一樣,只不過(guò)每次調(diào)用都是使用的新toast對(duì)象:
//將這兩行代碼toast.setText(text);//將文本設(shè)置給toasttoast.show(); 改為:toast.cancel()toast = Toast.makeText(app, text, Toast.LENGTH_LONG)toast.show()end
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Toast弹不出来之谜的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何线程安全的使用HashMap
- 下一篇: 从0开始配置Flutter并运行demo