1. 程式人生 > >轉 在子線程中new Handler報錯--Can't create handler inside thread that has not called Looper.prepare()

轉 在子線程中new Handler報錯--Can't create handler inside thread that has not called Looper.prepare()

tst exc 手動 tac new 聯網 clas 如果 read

在子線程中new一個Handler為什麽會報以下錯誤?

java.lang.RuntimeException:

Can‘t create handler inside thread that has not called Looper.prepare()

這是因為Handler對象與其調用者在同一線程中,如果在Handler中設置了延時操作,則調用線程也會堵塞。每個Handler對象都會綁定一個Looper對象,每個Looper對象對應一個消息隊列(MessageQueue)。如果在創建Handler時不指定與其綁定的Looper對象,系統默認會將當前線程的Looper綁定到該Handler上。
在主線程中,可以直接使用new Handler()創建Handler對象,其將自動與主線程的Looper對象綁定;在非主線程中直接這樣創建Handler則會報錯,因為Android系統默認情況下非主線程中沒有開啟Looper,而Handler對象必須綁定Looper對象。這種情況下,則有兩種方法可以解決此問題:

方法1:需先在該線程中手動開啟Looper(Looper.prepare()-->Looper.loop()),然後將其綁定到Handler對象上;

final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //執行耗時操作
    try {

      Log.e("bm", "runnable線程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());

      Thread.sleep(2000);
      Log.e("bm", "執行完耗時操作了~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    Looper.prepare();


    new Handler().post(runnable);//在子線程中直接去new 一個handler
    Looper.loop();    //這種情況下,Runnable對象是運行在子線程中的,可以進行聯網操作,但是不能更新UI
  }
}.start();

方法2:通過Looper.getMainLooper(),獲得主線程的Looper,將其綁定到此Handler對象上。

final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //執行耗時操作
    try {

      Log.e("bm", "runnable線程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
      Thread.sleep(2000);
      Log.e("bm", "執行完耗時操作了~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    new Handler(Looper.getMainLooper()).post(runnable)

;//在子線程中直接去new 一個handler

    //這種情況下,Runnable對象是運行在主線程中的,不可以進行聯網操作,但是可以更新UI
  }
}.start();

轉 在子線程中new Handler報錯--Can't create handler inside thread that has not called Looper.prepare()