HandlerThread 是一個封裝好的looper線程類尝蠕。
從源碼看看
public class HandlerThread extends Thread {
int mPriority; // 線程優(yōu)先級
int mTid = -1; // 修改線程優(yōu)先級片任、調(diào)度策略時用來做線程唯一標識
Looper mLooper; // 與線程關聯(lián)的Looper
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT; // 設置默認優(yōu)先級0
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority; // 主動設置優(yōu)先級
}
protected void onLooperPrepared() { //回調(diào)方法,looper開始前執(zhí)行
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); // 初始化一個Looper對象望伦,然后存入到ThreadLocal中,將Looper和當前線成進行綁定,一一對應.
synchronized (this) { // 進入同步塊
mLooper = Looper.myLooper(); //得到當前線程的looper對象
notifyAll();//通知其他線程
}
Process.setThreadPriority(mPriority); // 設置線程優(yōu)先級
onLooperPrepared(); // 回調(diào)重寫
Looper.loop(); // 一個死循環(huán)粒竖,不斷從MessageQueue取出消息氧骤,如有消息就處理呻疹,沒有就阻塞
mTid = -1; // 因為Looper.loop()是個死循環(huán)啊,執(zhí)行到mTid = -1的時候筹陵,就是looper退出的時候
}
public Looper getLooper() {
if (!isAlive()) { // 如果線程不是在存活狀態(tài)則直接返回null刽锤。
return null;
}
synchronized (this) {
while (isAlive() && mLooper == null) { // 進入同步塊镊尺,當條件不滿足時無限等待,
try { // 直到mLooper被設置成有效值了才退出等待
wait(); // run方法里的notifyAll就是用來喚醒這里的
} catch (InterruptedException e) { // 中斷異常
}
}
}
return mLooper; // 最后返回mLooper
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
quit()和 quitSafely()的區(qū)別:
removeAllMessagesLocked()是把MessageQueue消息池中所有的消息全部清空并思,無論延遲與否
removeAllFutureMessagesLocked()是只清空延遲消息庐氮,非延遲消息派發(fā)出去讓Handler去處理。
異步handler的創(chuàng)建方式
Thread newThread = new Thread(new Runnable()
{
@Override
public void run() {
Looper.prepare();
Looper.loop();
}
});
newThread.start();
Handler handler = new Handler(newThread.getLooper());
當執(zhí)行到Handler handler = new Handler(newThread.getLooper());的時候宋彼,newThread的looper可能還沒有創(chuàng)建好弄砍,會有線程同步的
問題。
總結:
1.不管調(diào)用哪個输涕,Looper就不再接收新的消息音婶,再通過Handler調(diào)用sendMessage發(fā)消息都只會返回false,Looper的quit方法從API Level 1就存在了莱坎,但是Looper的quitSafely方法從API Level 18才添加進來
2.HandlerThread本質(zhì)是一個Thread衣式,區(qū)別在于他在run()之后創(chuàng)建了一個含有消息隊列的Looper,這樣我們在子線程中創(chuàng)建Handler時候只需指定使用HandlerThread中的Looper檐什,不用再調(diào)用Looper.prepare(),looper.loop()碴卧,并且做了同步的處理,簡化了操作乃正。
3.另外Handler與Activity在同一個線程中螟深,不能做耗時操作。HandlerThread是新的線程烫葬,可做耗時操作
舉例:
public class MainActivity extends Activity {
private Handler handlerthread;
private HandlerThread thread;
//創(chuàng)建主線程中的handler
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
Message message = new Message();
handlerthread.sendMessageDelayed(message, 1000);
Log.d("wuc", "主線程");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt_test = (Button)findViewById(R.id.bt_test);
bt_test.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handlerthread.sendEmptyMessage(1);
}
});
thread = new HandlerThread("threadHandler");
thread.start();
handlerthread = new Handler(thread.getLooper()){
@Override
public void handleMessage(Message msg) {
Message message = new Message();
//handler每隔1秒向主線程發(fā)送一次消息界弧。
Log.d("wuc", "子線程");
handler.sendMessageDelayed(message, 1000);
}
};
}
}
04-26 16:49:26.822 7349-7385/com.example.lyf.androidtext D/wuc: 子線程
04-26 16:49:27.822 7349-7349/com.example.lyf.androidtext D/wuc: 主線程
04-26 16:49:28.823 7349-7385/com.example.lyf.androidtext D/wuc: 子線程
04-26 16:49:29.826 7349-7349/com.example.lyf.androidtext D/wuc: 主線程
04-26 16:49:30.826 7349-7385/com.example.lyf.androidtext D/wuc: 子線程
04-26 16:49:31.827 7349-7349/com.example.lyf.androidtext D/wuc: 主線程
04-26 16:49:32.828 7349-7385/com.example.lyf.androidtext D/wuc: 子線程