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()

在子執行緒中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();

  

from:https://www.cnblogs.com/jingmo0319/p/5730963.html