1. Fundamentals
HandlerThread是一個內部包含Thread,Looper,MessageQueue的線程。HandlerThread 開啓之後,它就會創建一個Looper和MessageQueue的隊列,等待處理髮送過來的消息。
Eg:
HandlerThread handlerThread = new HandlerThread("handlerthread");
handlerThread.start();
// 實例化Handler時,使用HandlerThread的Looper,這樣實例化後的Handler屬於HandlerThread線程中的,Handler發送的message就會到HandlerThread(Worker Thread)的MessageQueue中,
// 然後在Handler的handleMessage方法中處理髮送來的message
mHandler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// TODO: process message
}
}
如果在HandlerThread開始之前有其他額外的需要設置的,那麼需要重寫HandlerThread.onLooperPrepared()方法,這個方法在Looper被prepared時候會在background thread中調用。例如,我們可以在onLooperPrepared()方法中創建一個Handler,輔助HandlerThread處理消息。
Eg:
public class MyHandlerThread extends HandlerThread {
private final String TAG = MyHandlerThread.class.getSimpleName();
private Handler mHandler = null;
public MyHandlerThread(String name) {
super("myhandlerthread", Process.THREAD_PRIORITY_BACKGROUND);
}
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
mHandler = new Handler(getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
Log.i(TAG, "MyHandlerThread # onLooperPrepared # what is 1");
break;
}
}
};
}
public void sendMessage1() {
mHandler.sendEmptyMessage(1);
}
}
2. Lifecycle
一個正在運行的HandlerThread實例對象處理接收到Message直到它被終止,一個終止的HandlerThread不能重用。
Creation
構造方法:
HandlerThread(String name)
HandlerThread(String name, int priority)
Execution
調用HandlerThread.start()方法開始運行
Reset
message queue能夠被重置,重置會刪除message queue中所有待處理的message,但是那些已經被diapatch出去或者正在執行的message不受影響,同時這個thread還是alive的,也能處理新發生來的message。
Eg:
public void resetHandlerThread() {
mHandler.removeCallbackAndMessages(null);
}
Termination
第一種方法:
調用HandlerThread的quit()或者quitSafely()方法來終止,調用這個方法相當於終止了Looper。
Eg:
public void stopHandlerThread(HandlerThread handlerThread) {
handlerThread.quit();
// 調用interrupt()方法,這樣HandlerThread就會取消正在執行的message
handlerThread.interrupt();
}
第二種方法:
通過Handler發送一個終止任務來退出Looper,從而終止HandlerThread
Eg:
handler.post(new Runnable() {
@Override
public void run() {
Looper.myLooper().quit();
}
});
3. Demo
因爲HandlerThread中MessageQueue是線性處理的,因此可以依賴這個性質,使用HandlerThread處理有順序要求的任務。
例如使用HandlerThread處理有順序要求的網絡請求,當同一個網絡請求返回成功後,才能進行下一個網絡請求。
Eg:
public class ChainedNetworkActivity extends Activity {
private static final int DIALOG_LOADING = 0;
private static final int SHOW_DIALOG = 1;
private static final int DISMISS_DIALOG = 2;
private DialogHandler dialogHandler = null;
private NetworkHandlerThread networkHandlerThread = null;
private static class DialogHandler extends Handler {
private WeakReference<ChainedNetworkActivity> activity = null;
public DialogHandler(ChainedNetworkActivity activity) {
this.activity = new WeakReference<ChainedNetworkActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SHOW_DIALOG:
if (activity != null) {
activity.get().showDialog(DIALOG_LOADING);
}
break;
case DISMISS_DIALOG:
if (activity != null) {
activity.get().dismissDialog(DIALOG_LOADING);
}
break;
}
}
}
private class NetworkHandlerThread extends HandlerThread {
private final int STATE_A = 1;
private final int STATE_B = 2;
private Handler handler = null;
public NetworkHandlerThread() {
super("networkhandlerthread", Process.THREAD_PRIORITY_BACKGROUND);
}
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
handler = new Handler(getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case STATE_A:
dialogHandler.sendEmptyMessage(SHOW_DIALOG);
String resultA = network1();
if (resultA != null) {
// 當第一個網絡請求成功後,進行下一個
sendMessage(obtainMessage(STATE_B, resultA));
} else {
dialogHandler.sendEmptyMessage(DISMISS_DIALOG);
}
break;
case STATE_B:
network2((String) msg.obj);
dialogHandler.sendEmptyMessage(DISMISS_DIALOG);
break;
}
}
};
// 開始一個網絡請求
handler.sendEmptyMessage(STATE_A);
}
private String network1() {
SystemClock.sleep(1000);
return "State 1";
}
private String network2(String preResult) {
SystemClock.sleep(1000);
return preResult + " - State B";
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialogHandler = new DialogHandler(this);
networkHandlerThread = new NetworkHandlerThread();
networkHandlerThread.start();
}
@Override
protected Dialog onCreateDialog(int id) {
Dialog dialog = null;
switch (id) {
case DIALOG_LOADING:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Loading...");
dialog = builder.create();
break;
}
return dialog;
}
@Override
protected void onDestroy() {
super.onDestroy();
networkHandlerThread.quit();
}
}