一、遇到的問題——調用了Looper.loop()會發(fā)生什么
最近在使用Thread的時候遇到了這樣一個問題,在子線程Thread中顯示一條Toast,在run()方法中增加了Looper.prepare()以及 Looper.loop(),發(fā)現改線程無法被銷毀。
具體如下:
final Thread testThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(MainActivity.this,"測試toast",Toast.LENGTH_SHORT).show();
Looper.loop();
}
});
testThread.start();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.i("xx","線程狀態(tài):"+testThread.getState());
}
},10000);
輸出日志如下:
09-01 18:43:45.991 17336-17336/net.loosash.learnthread I/xx: 線程啟動
09-01 18:43:55.998 17336-17336/net.loosash.learnthread I/xx: 線程狀態(tài):RUNNABLE
這也就證明了該Thread會一直執(zhí)行,不會被銷毀,可能會發(fā)生內存泄漏。那么,該如何處理這個問題呢?
二、解決線程銷毀問題
這種情況需要主動處理線程的銷毀,在不需要的時候關閉線程。
關閉線程的方法已經有很多人總結了。網上一搜一大把
https://blog.csdn.net/zhangtengyuan23/article/details/50535813/
三、引發(fā)相關的思考——HandlerThread
遇到這個問題,我第一個想法是HandlerThread,因為這個在android SDK中提供的類內部也維護了一個Looper,并且提供了quit()方法,在使用HandlerThread的時候也要在不需要的時候進行quit()的調用。
這里是HandlerThread的使用方法
https://blog.csdn.net/double2hao/article/details/58598171
四、引發(fā)相關的思考——ActivityThread主線程的消息機制
雖然ActivityThread并不是繼承與Thread,但是作為主線程,內部也維護了一個Looper,以便主線程一直在不停的循環(huán)執(zhí)行,不至于主線程結束掉,導致進程結束。所以我認為最開始的問題,調用了Looper.loop()后,線程進入了死循環(huán),無法自動跳出,導致線程一直存在,無法被銷毀。
五、關于Looper的一些常識
- 1、線程里一定會有Looper的實例么?
答案是否定的,Thread是基于java的(package java.lang包中),而Looper是基于android系統(tǒng)的(package android.os包中),所以二者并沒有必然聯系; - 2、Looper的作用是什么?
簡單的說,Looper的作用是處理進程間的消息的,以便實現進程間通訊,是Handler機制的一部分,用來輪訓MessageQueue中的Message,實現接收Message。Handler機制的實現是利用消息隊列的方式,為用戶封裝了一層API,用戶不需要考慮互斥枷鎖的問題,方便用戶的使用。 - 3、Looper的使用方法
就是像上面的例子一樣,顯示Toast,子線程間通訊,這里簡單列舉幾條
// 顯示toast
Thread testThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(MainActivity.this,"測試toast",Toast.LENGTH_SHORT).show();
Looper.loop();
}
});
// 在子線程中接收使用Handler發(fā)來的消息
Thread testThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mHandler = new Handler(Looper.myLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//do Something
}
};
Looper.loop();
}
});
六、Looper.loop()到底做了什么——源碼分析
晚點補充吧