Toast彈不出來之謎
阿新 • • 發佈:2018-12-14
前言
今天早上測試應用的時候,忽然發現Toast彈不出來了,我用的華為測試機,以為是通知許可權被關了,後來發現是開著的,這就納了悶了,這個Toast工具類用了好長時間了,後來發現這Toast原來還能這樣...
正文
以前工具類是這個樣子的(華為的通知許可權放在了其他的地方)
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(); } }
平時用的都是好好的,為什麼不能用了呢?
然後我通過debug發現所有路徑都走了,說明是呼叫成功了,後來想起來,是不是子執行緒的問題,列印了一下執行緒資訊:
Thread.currentThread().getName();
發現果然第一次呼叫沒有跑在主執行緒中,這就尷尬了,在子執行緒中建立,並show()竟然沒有報錯,而且子執行緒建立的在主執行緒呼叫show()也沒有報錯,只是不顯示
到show()的原始碼中發現,被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 } }
修改方法
在建立和show的時候可以判斷是否是主執行緒,如果不是就放到主執行緒中就ok了
修改後的程式碼,嗯,這樣就可以了(雖然有強迫症看到這程式碼很不爽,但是首先得能用)
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().runOnUiThread(new Runnable() { @Override public void run() { toast = Toast.makeText(App.getInstance(), text, Toast.LENGTH_SHORT); toast.show(); } }); } else { //如果show()是在子執行緒觸發的,則在主執行緒來顯示 if ("main".equals(Thread.currentThread().getName())) { toast.setText(text);//將文字設定給toast toast.show(); } else { AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() { @Override public void run() { toast.setText(text);//將文字設定給toast toast.show(); } }); } } } }
end