HandlerThread是Android API提供的一個便捷的線程類,使用它我們可以快速地創(chuàng)建一個帶有Looper的線程,而這個Looper是和線程一對一綁定的。有了這個Looper之后,我們又可以生成工作在這個線程里面的Handler。
實現(xiàn)原理
在介紹原理之前,我們先用普通的Thread來創(chuàng)建一個Handler,過程大致如下:
Handler handler;
private void createMannualThreadWithHandler(){
new Thread(){
@Override
public void run(){
super.run();
Looper.prepare();
handler = new Handler(Looper.myLooper());
Looper.loop();
}
}.start();
}
實現(xiàn)很簡單,需要在目標線程中做如下配置
- 調用Looper.prepare()創(chuàng)建與當前線程綁定的Looper實例
- 使用上面創(chuàng)建的Looper生成Handler實例
- 調用Looper.loop()實現(xiàn)消息循環(huán)
注意:
Looper.prepare()在一個線程中只能調用一次,否則會拋出異常;Looper.loop()方法是一個死循環(huán),需要使用quit()/quitSafely()退出。
明白了上面的實現(xiàn)步驟,HandlerThread的實現(xiàn)也就簡單了,源碼如下:
@Override
public void run(){
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
Handler原理
理解Handler的原理,只需記住以下幾點即可:
- Message意為消息,發(fā)送到Handler進行處理的對象,攜帶描述性的信息和數(shù)據(jù)。
- MessageQueue意為消息隊列,Message的集合。
- Looper意為消息泵,用來從MessageQueue中抽取Message,發(fā)送給相應的Handler進行處理。
- Handler處理Looper抽取出來的Message。
如何使用
HandlerThread使用起來很容易,首先下以后進行初始化。
private Handler handler;
private LightTaskManager(){
HandlerThread workerThread = new HandlerThread("LightTaskThread");
workerThread.start();
handler = new Handler(workerThread.getLooper());
}
注意,上面的workerThread.start();必須要先執(zhí)行。
至于如何使用HandlerThread來執(zhí)行任務,主要是調用Handler的API。
下面給出使用HandlerThread創(chuàng)建一個工作在新線程的Service組件。
使用HandlerThread創(chuàng)建一個工作在新的線程的Service組件的代碼框架如下:
public class LDMService extends Service{
private HandlerThread ldmThread;
private LDMHandler ldmHandler;
final class LDMHandler extends Handler{
public LDMHandler(Looper looper){
// 將Handler和looper綁定
super(looper);
}
@Override
public void handleMessage(Message msg){
// TODO:處理消息的應用邏輯
}
}
@Override
public void onCreate(){
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
ldmThread = new HandlerThread("LDM Service Thread", Process.THREAD_PRIORITY_BACKGROUND);
ldmThread.start;
ldmHandler = new LDMHandler(ldmThread.getLooper());
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onDestroy(){
ldmThread.quitSafely();
}
}