Handler機制是Android中最神奇的機制之一
主要應用:
1. 定時、延遲執行
2. 跨頁面傳遞數據發起事件
3. 跨線程執行
Handler機制分爲:Handler、Loop、MessageQueue、Message四個類
關係:一個Thread對應一個Loop,一個Loop對應一個MessageQueue,一個MessageQueue對應多個Message,一個Message對應一個Handler
Handler關係類圖:
Handler運行流程圖:
Question:
1.子線程是如何將runnable post到主線程運行的?
答:其實在自線程中運行runnable.post方法,真正的作用:
1. Message.obtion一個Message
2. Message.callback = runnable ,將runnable賦值給message的callback變量
3. 執行了MessageQueue.enqueueMessage方法,將此Message添加到Message通過next指針構成的列表頭部(或者頭部第二個)
4. 調用nativeWake(mPtr);通知MessageQueue中的nativePollOnce(ptr, nextPollTimeoutMillis);甦醒
5. 繼續在他之前運行的線程中(這裏是主線程)運行next()抓取Message,交給Looper.loop
6. loop調用Message對應Handler的dispatchMessage方法
7. 調用Handler的handleCallback方法
8. 最終執行message.callback.run()
最終在主線程中跑完了這個runnable方法
2.Looper.looper()、MessageQueue.next爲何不會阻塞?
答:其實流程圖已經給出了答案:
MessageQueue.next()方法會調用nativePollOnce(ptr, nextPollTimeoutMillis);進行休息,讓本線程的其它邏輯先運行,發現有新的Message通過MessageQueue的enqueueMessage()方法添加,會調用nativeWake(mPtr);通知nativePollOnce(ptr, nextPollTimeoutMillis);甦醒繼續執行。運行結束之後又會繼續休息,循環往復
3.handler爲何會導致內存泄漏?如何避免?
答:handler可以通過xxxdelay()方法,延遲dispatchMessage運行,如果在等待的這段時間相應Activity關閉掉,那麼之前發出去的message內部還通過target持有handler對象,而handler爲activity的內部成員,所以這段時間內activity會因爲內部成員handler無法被釋放而無法釋放內存,故這段時間內會導致內存泄漏。
解決辦法:handler.removeCallbacksAndMessages(null);
會調用MessageQueue的removeCallbacksAndMessages方法
內部的邏輯是如果參數爲null,那麼會調用當前線程所有的Message的recycleUnchecked方法,此方法會將內部所有變成置空,等待垃圾回收器回收。
4.message爲何不會分發到錯誤的handler?
答:因爲每個Message有一個target變量指定了其所需要運行的Handler
5.子線程如何創建並使用handler?
package com.test.looper;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class MainActivity extends Activity {
private LooperThread looperThread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
looperThread = new LooperThread();
looperThread.start();
looperThread.getHandler().sendEmptyMessage(1);
}
class LooperThread extends Thread {
private Handler mHandler;
private final Object mSync = new Object();
public void run() {
// 自線程中需要手動Looper.prepare以及手動loop
// 需要注意的是:在創建Handler之前需要先執行Looper.prepare
Looper.prepare();
synchronized (mSync) {
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Log.d("CYQ", "--->" + msg);
}
};
mSync.notifyAll();
}
Looper.loop();
}
public Handler getHandler() {
synchronized (mSync) {
if (mHandler == null) {
try {
mSync.wait();
} catch (InterruptedException e) {
}
}
return mHandler;
}
}
public void exit() {
getHandler().post(new Runnable(){
public void run() {
Looper.myLooper().quit();
}});
}
}
}
面試中還有時候會問:如何實現主線程向子線程發送消息?(上面的代碼就是答案)
其實瞭解Handler機制之後,道理都一樣的:
僅僅是在主線程中調用自線程的handler,發送消息,子線程自己會通過MessageQueue.next方法跑子線程的message
自己寫了個Handler工具類,方便各線程獲取自己線程的Handler、主線程的Handler:
/**
* Handler幫助類
*
* @author yuanyang
*
*/
public class HandlerUtils {
private HandlerUtils() {
}
private static class Holder {
public static HandlerUtils instance = new HandlerUtils();
}
public static HandlerUtils getInstance() {
return Holder.instance;
}
private Handler mHandler;
/**
* 獲取新Handler,子線程沒有Looper就用主線程的Handler
*/
public Handler getNewHandler() {
Looper myLooper = Looper.myLooper();
Looper mainLooper = Looper.getMainLooper();
if (myLooper == null) {
mHandler = new Handler(mainLooper);
} else {
mHandler = new Handler(myLooper);
}
return mHandler;
}
/**
* 獲取新Handler,子線程沒有Looper就用主線程的Handler
*/
public Handler getNewHandlerCB(final HandlerDispose hd) {
Looper myLooper = Looper.myLooper();
Looper mainLooper = Looper.getMainLooper();
if (myLooper == null) {
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
} else {
mHandler = new Handler(myLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
}
return mHandler;
}
/**
* 獲取子線程Handler
*/
public Handler getNewChildHandler() {
Looper myLooper = Looper.myLooper();
if (myLooper == null) {
Looper.prepare();
mHandler = new Handler(Looper.myLooper());
Looper.loop();
} else {
mHandler = new Handler(myLooper);
}
return mHandler;
}
/**
* 獲取子線程Handler
*/
public Handler getNewChildHandlerCB(final HandlerDispose hd) {
Looper myLooper = Looper.myLooper();
if (myLooper == null) {
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
Looper.loop();
} else {
mHandler = new Handler(myLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
}
return mHandler;
}
/**
* 獲取UI線程Handler
*/
public Handler getUIHandler() {
// 若成員變量Handler爲
if (mHandler != null) {
if (mHandler.getLooper() == Looper.getMainLooper()) {
return mHandler;
}
}
Looper mainLooper = Looper.getMainLooper();
mHandler = new Handler(mainLooper);
return mHandler;
}
/**
* 獲取UI線程Handler
*/
public Handler getUIHandlerCB(final HandlerDispose hd) {
Looper mainLooper = Looper.getMainLooper();
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
return mHandler;
}
/**
* UI界面關閉的時候清空Handler,方式內存泄漏
*/
public void UIOnFinish() {
mHandler = null;
}
/**
* Handler的回調接口
*
* @author yuanyang
*
*/
public interface HandlerDispose {
public void handleMessage(android.os.Message msg);
}
}