在子線程中new一個(gè)Handler為什么會(huì)報(bào)以下錯(cuò)誤蝗羊?
java.lang.RuntimeException:
Can't create handler inside thread that has not called Looper.prepare()
這是因?yàn)镠andler對(duì)象與其調(diào)用者在同一線程中,如果在Handler中設(shè)置了延時(shí)操作,則調(diào)用線程也會(huì)堵塞。每個(gè)Handler對(duì)象都會(huì)綁定一個(gè)Looper對(duì)象福也,每個(gè)Looper對(duì)象對(duì)應(yīng)一個(gè)消息隊(duì)列(MessageQueue)。如果在創(chuàng)建Handler時(shí)不指定與其綁定的Looper對(duì)象攀圈,系統(tǒng)默認(rèn)會(huì)將當(dāng)前線程的Looper綁定到該Handler上暴凑。
在主線程中,可以直接使用new Handler()創(chuàng)建Handler對(duì)象赘来,其將自動(dòng)與主線程的Looper對(duì)象綁定现喳;在非主線程中直接這樣創(chuàng)建Handler則會(huì)報(bào)錯(cuò),因?yàn)锳ndroid系統(tǒng)默認(rèn)情況下非主線程中沒(méi)有開(kāi)啟Looper犬辰,而Handler對(duì)象必須綁定Looper對(duì)象拿穴。這種情況下,則有兩種方法可以解決此問(wèn)題:
方法1:需先在該線程中手動(dòng)開(kāi)啟Looper(Looper.prepare()-->Looper.loop())忧风,然后將其綁定到Handler對(duì)象上默色;
final Runnable runnable = new Runnable() {
@Override
public void run() {
//執(zhí)行耗時(shí)操作
try {
Log.e("bm", "runnable線程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
Thread.sleep(2000);
Log.e("bm", "執(zhí)行完耗時(shí)操作了~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread() {
public void run() {
Looper.prepare();
new Handler().post(runnable);//在子線程中直接去new 一個(gè)handler
Looper.loop(); //這種情況下,Runnable對(duì)象是運(yùn)行在子線程中的狮腿,可以進(jìn)行聯(lián)網(wǎng)操作腿宰,但是不能更新UI
}
}.start();
方法2:通過(guò)Looper.getMainLooper(),獲得主線程的Looper缘厢,將其綁定到此Handler對(duì)象上吃度。
final Runnable runnable = new Runnable() {
@Override
public void run() {
//執(zhí)行耗時(shí)操作
try {
Log.e("bm", "runnable線程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
Thread.sleep(2000);
Log.e("bm", "執(zhí)行完耗時(shí)操作了~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread() {
public void run() {
new Handler(Looper.getMainLooper()).post(runnable);//在子線程中直接去new 一個(gè)handler
//這種情況下,Runnable對(duì)象是運(yùn)行在主線程中的贴硫,不可以進(jìn)行聯(lián)網(wǎng)操作椿每,但是可以更新UI
}
}.start();