【轉】在子執行緒中new Handler報錯--Can't create handler inside thread that has not called Looper.prepare()
阿新 • • 發佈:2018-12-15
在子執行緒中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