自己親測兩種解決方法:
1、將Toast換成dialog,呵呵,這個方法比較土鱉,但是很好用。而且不用費力去理原有代碼的流程。
原因:Toast在傳入context的時候,不管你傳的是activity還是application,他都是調用的mContext.getPackageName();這也是爲什麼只有卸載應用才能將Toast消除。但是dialog就不一樣,他是依賴activity本身的,如果activity退出了,activity附屬的dialog也就自然被回收了。補充<span style="font-family: Arial; font-size: 16px; line-height: 24px; background-color: rgb(237, 237, 237);">,當由於</span><span style="font-family: Arial; font-size: 16px; line-height: 24px; background-color: rgb(237, 237, 237);">HandlerThread沒quiet,而activity退出的時候,Toast無法調用相應的hide方法,導致Toast不消失。</span>
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
2、方法二就是常規的處理方式,在onpause方法裏也加個HandlerThread.quiet.
Toast是Android一個比較省心的控件,因爲Toast不提供任何交互界面,看一眼就消失,而且只需要Context就可以創建。
然而無須交互的優勢這也帶來一個問題,如果Toast顯示後無法消失,那麼將真的是無法消失了。除非強制退出應用或者重啓手機。
一個簡單的示例程序,就可以創造出一個無法消失的Toast。以下爲Activity代碼:
public class ToastTestActivity extends Activity {
/** HandlerThread object */
HandlerThread mThread = null;
/** Handler object */
ToastHandler mHandler = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mThread = new HandlerThread("ToastThread");
mThread.start();
mHandler = new ToastHandler(mThread.getLooper());
}
/**
* Called when Button got clicked
* @param v View that got clicked
*/
public void myClick(View v) {
mHandler.sendEmptyMessageDelayed(1, 2000);
}
private class ToastHandler extends Handler {
public ToastHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast toast = Toast.makeText(ToastTestActivity.this, "Dismiss me", Toast.LENGTH_LONG);
toast.show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeMessages(1);
mThread.getLooper().quit();
mHandler = null;
mThread = null;
}
}
該Activity有一個Button, 點擊之後會向HandlerThread發送一個延時消息,Handler處理該消息時會創建並顯示一個Toast,當Toast正在顯示的時候,點Back鍵退出Activity。就會發現正在顯示的Toast不會消失。
原因:
罪魁禍首就是HandlerThread在onDestroy方法裏面調用了HandlerThread.getLooper().quit()。因爲Toast在創建的時候,會同時創建一個基於當前線程的Handler對象,雖然NotificationManagerService負責調度Toast,但是真正顯示和隱藏Toast都是向這個Handler發送消息。也就是說Toast做事情也用到了HandlerThread的Looper。所以如果單純在onDestroy方法裏將Looper給quit的話,Toast將無法實現隱藏。
解決方案:
個人感覺讓Toast遠離HandlerThread比較靠譜。可以統一規範代碼,所有顯示Toast的代碼都post到主線程(無論是Activity還是Service)當中,因爲主線程的Looper不會輕易quit,至少不會允許開發者顯示quit。