1. 程式人生 > >android 提示異常:java.lang.RuntimeException: Can't create handler inside thread that has not called

android 提示異常:java.lang.RuntimeException: Can't create handler inside thread that has not called

出現此異常,可能是在子執行緒彈Toast/Dialog或者其他了, 切記,Toast/Dialog只能在UI執行緒彈出。
處理的話,要麼子執行緒也可以,要麼都放主執行緒,以下兩種方式分別對應。

Android-在子執行緒中顯示Toast和Dialog

Android中有句話說,只能在主執行緒(UI執行緒)中更新UI,這是因為Android的主執行緒(UI執行緒)是不安全的。所以在子執行緒如果要顯示Toast或者Dialog,我們需要通知主執行緒來顯示 ,有兩種方法可以解決此問題:

(1)在UI程式碼的前後加上Loop.prepare()和Loop.loop();例如:

Looper.prepare(); 
showExitDialog(App.getInstance().getCurrentActivity()); 
Looper.loop(); 

(2)通過handler訊息來建立,具體方法是建立一個handler,然後在子執行緒中傳送一個Message訊息,在handler收到訊息後建立Toast或Dialog.


public class DialogActivity extends Activity{
		@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new Thread(new TestThread(this)).start();
    }


    Handler hmessage = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                dialog();
                Toast.makeText(DialogActivity.this, "333", Toast.LENGTH_LONG).show();
            }
            super.handleMessage(msg);
        }
    };

    private void dialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("確認退出嗎?");
        builder.setTitle("提示");
        builder.setPositiveButton("確認", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.create().show();
    }


    class TestThread implements Runnable {
        private DialogActivity da = null;

        public TestThread(DialogActivity da) {
            this.da = da;
        }

        @Override
        public void run() {
            hmessage.sendEmptyMessage(1);
        }

    }
}

注:
1、Looper用來為一個執行緒開啟一個訊息迴圈。預設情況下,子執行緒是有沒有Looper的。Looper通過MessageQueue來存放訊息和事件,一個執行緒只能有一個Looper,對應一個MessageQueue。
2、在子執行緒中直接new Handler()會報錯,原因是沒有建立Looper,需先用Looper.prepare啟用Looper。
Looper.loop()讓Looper開始工作。