handler 的使用
//使用匿名內(nèi)部類創(chuàng)建handler
public static Handler handler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
};
};
//構(gòu)建消息
Message message = Message.obtain();
message.what = 1;
//發(fā)送消息
handler.sendMessage(message);
//延時(shí)發(fā)送消息
handler.sendMessageDelayed(message,1000);
//直接處理
handler.post(new Runnable() {
@Override
public void run() {
}
});
分析1:(創(chuàng)建handler
)
@Deprecated
public Handler() {
this(null, false);
}
public Handler(@Nullable Handler.Callback callback, boolean async) {
...
//獲取當(dāng)前線程的Looper
mLooper = Looper.myLooper();
//如果沒(méi)有l(wèi)ooper直接拋出異常
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
// Looper.myLooper()作用:獲取當(dāng)前線程的Looper對(duì)象;若線程無(wú)Looper對(duì)象則拋出異常
// 即 :若線程中無(wú)創(chuàng)建Looper對(duì)象,則也無(wú)法創(chuàng)建Handler對(duì)象
// 故 若需在子線程中創(chuàng)建Handler對(duì)象,則需先創(chuàng)建Looper對(duì)象
// 注:可通過(guò)Loop.getMainLooper()可以獲得當(dāng)前進(jìn)程的主線程的Looper對(duì)象
// 2. 綁定消息隊(duì)列對(duì)象(MessageQueue)
mQueue = mLooper.mQueue;
// 獲取該Looper對(duì)象中保存的消息隊(duì)列對(duì)象(MessageQueue)
// 至此,保證了handler對(duì)象 關(guān)聯(lián)上 Looper對(duì)象中MessageQueue
mCallback = callback;
mAsynchronous = async;
mCallback = callback;
mAsynchronous = async;
}
分析二(創(chuàng)建Looper)
private static void prepare(boolean quitAllowed) {
// 1. 判斷sThreadLocal是否為null,否則拋出異常
//即 Looper.prepare()方法不能被調(diào)用兩次 = 1個(gè)線程中只能對(duì)應(yīng)1個(gè)Looper實(shí)例
// 注:sThreadLocal = 1個(gè)ThreadLocal對(duì)象,用于存儲(chǔ)線程的變量
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 2. 若為初次Looper.prepare(),則創(chuàng)建Looper對(duì)象 & 存放在ThreadLocal變量中
// 注:Looper對(duì)象是存放在Thread線程里的
// 源碼分析Looper的構(gòu)造方法->>分析a
sThreadLocal.set(new Looper(quitAllowed));
}
@Deprecated
public static void prepareMainLooper() {
//創(chuàng)建looper
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
private Looper(boolean quitAllowed) {
// 1. 創(chuàng)建1個(gè)消息隊(duì)列對(duì)象(MessageQueue)
// 即 當(dāng)創(chuàng)建1個(gè)Looper實(shí)例時(shí),會(huì)自動(dòng)創(chuàng)建一個(gè)與之配對(duì)的消息隊(duì)列對(duì)象(MessageQueue)
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
// 在Android應(yīng)用進(jìn)程啟動(dòng)時(shí),會(huì)默認(rèn)創(chuàng)建1個(gè)主線程(ActivityThread,也叫UI線程)
// 創(chuàng)建時(shí),會(huì)自動(dòng)調(diào)用ActivityThread的1個(gè)靜態(tài)的main()方法 = 應(yīng)用程序的入口
// main()內(nèi)則會(huì)調(diào)用Looper.prepareMainLooper()為主線程生成1個(gè)Looper對(duì)象
public static void main(String[] args) {
...
Looper.prepareMainLooper();
// 1. 為主線程創(chuàng)建1個(gè)Looper對(duì)象,同時(shí)生成1個(gè)消息隊(duì)列對(duì)象(MessageQueue)
// 方法邏輯類似Looper.prepare()
// 注:prepare():為子線程中創(chuàng)建1個(gè)Looper對(duì)象
ActivityThread thread = new ActivityThread();
// 2. 創(chuàng)建主線程
Looper.loop();
// 3. 自動(dòng)開(kāi)啟 消息循環(huán) ->>下面將詳細(xì)分析
throw new RuntimeException("Main thread loop unexpectedly exited");
}
分析三(Looper.loop實(shí)現(xiàn)消息循環(huán))
public static void loop() {
final Looper me = myLooper();
//先看有么有l(wèi)ooper,沒(méi)有直接拋異常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
me.mInLoop = true;
//獲取MessageQueue
final MessageQueue queue = me.mQueue;
...
//死循環(huán)去獲取MessageQueue里邊的消息
for (;;) {
//獲取Message 有可能阻塞在這里
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
try {
//分發(fā)消息 msg.target是一個(gè)Handler
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
}
//釋放消息占據(jù)的資源
msg.recycleUnchecked();
}
}
@UnsupportedAppUsage
Message next() {
...
// 該參數(shù)用于確定消息隊(duì)列中是否還有消息
// 從而決定消息隊(duì)列應(yīng)處于出隊(duì)消息狀態(tài) or 等待狀態(tài)
//如果等于-1表示沒(méi)有消息
int nextPollTimeoutMillis = 0;
//for循環(huán)
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// nativePollOnce方法在native層,若是nextPollTimeoutMillis為-1,此時(shí)消息隊(duì)列處于等待狀態(tài)
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// 出隊(duì)消息,即 從消息隊(duì)列中取出消息:按創(chuàng)建Message對(duì)象的時(shí)間順序
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
//取出下一條消息
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
//延時(shí)的處理,計(jì)算定時(shí)喚醒時(shí)間
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
//4.獲取到一條消息,因?yàn)槭窍㈥?duì)列是鏈表結(jié)構(gòu),所以需要調(diào)整一下鏈表
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
// 若 消息隊(duì)列中已無(wú)消息,則將nextPollTimeoutMillis參數(shù)設(shè)為-1
// 下次循環(huán)時(shí),消息隊(duì)列則處于等待狀態(tài)
nextPollTimeoutMillis = -1;
}
...
//5.這里提到 IdleHandler,是個(gè)什么東西?下面會(huì)分析
//在獲取不到message的時(shí)候才會(huì)走的代碼,也就可以理解為 IdleHandler是消息隊(duì)列空閑(或者主線程空閑)時(shí)候才會(huì)執(zhí)行的Handler。
//IdleHandler 是一個(gè)接口,只有一個(gè)方法 queueIdle() ,調(diào)用addIdleHandler(IdleHandler handler) 這個(gè)方法的時(shí)候會(huì)將handler添加到list中
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
分析四(處理消息)
//分發(fā)消息
public void dispatchMessage(Message msg) {
// 1. 若msg.callback屬性不為空,則代表使用了post(Runnable r)發(fā)送消息
// 則執(zhí)行handleCallback(msg),即回調(diào)Runnable對(duì)象里復(fù)寫(xiě)的run()
// 上述結(jié)論會(huì)在講解使用“post(Runnable r)”方式時(shí)講解
if (msg.callback != null) {
//當(dāng)使用handler.post()的時(shí)候會(huì)調(diào)用該方法
//因?yàn)閙sg自帶一個(gè)callback
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 2. 若msg.callback屬性為空,則代表使用了sendMessage(Message msg)發(fā)送消息(即此處需討論的)
// 則執(zhí)行handleMessage(msg),即回調(diào)復(fù)寫(xiě)的handleMessage(msg) ->> 分析3
handleMessage(msg);
}
}
/**
* 分析3:handleMessage(msg)
* 注:該方法 = 空方法,在創(chuàng)建Handler實(shí)例時(shí)復(fù)寫(xiě) = 自定義消息處理方式
**/
public void handleMessage(Message msg) {
... // 創(chuàng)建Handler實(shí)例時(shí)復(fù)寫(xiě)
}
分析五(發(fā)送一條消息)
public final boolean sendMessage(@NonNull Message msg) {
//調(diào)用延時(shí)發(fā)送消息
return sendMessageDelayed(msg, 0);
}
//延時(shí)發(fā)送消息
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
//獲取消息隊(duì)列對(duì)象
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
//插入一條消息
return enqueueMessage(queue, msg, uptimeMillis);
}
//插入一條消息
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
// 1. 將msg.target賦值為this
// 即 :把 當(dāng)前的Handler實(shí)例對(duì)象作為msg的target屬性
msg.target = this;
// 請(qǐng)回憶起上面說(shuō)的Looper的loop()中消息循環(huán)時(shí),會(huì)從消息隊(duì)列中取出每個(gè)消息msg,然后執(zhí)行msg.target.dispatchMessage(msg)去處理消息
// 實(shí)際上則是將該消息派發(fā)給對(duì)應(yīng)的Handler實(shí)例
// 2. 調(diào)用消息隊(duì)列的enqueueMessage()
// 即:Handler發(fā)送的消息,最終是保存到消息隊(duì)列
return queue.enqueueMessage(msg, uptimeMillis);
}
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 判斷消息隊(duì)列里有無(wú)消息
// 1. 若無(wú),則將當(dāng)前插入的消息 作為隊(duì)頭 & 若此時(shí)消息隊(duì)列處于等待狀態(tài),則喚醒
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// 2.否則插到鏈表中間,需要移動(dòng)鏈表
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
// 鏈表移動(dòng),延時(shí)的消息會(huì)插入到合適的位置
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
總結(jié)
1.在應(yīng)用啟動(dòng)的時(shí)候,也就是ActivityThread的main方法里面,創(chuàng)建了Looper和MessageQueue,然后調(diào)用Looper.loop 開(kāi)啟消息循環(huán)
2.消息循環(huán)是這樣的,調(diào)用MessageQueue的next方法,循環(huán)從消息隊(duì)列中取出一條消息,然后交給Handler去處理,一般是回調(diào)handleMessage方法,取不到消息就阻塞,直到下一個(gè)消息入隊(duì)或者其它延時(shí)消息到時(shí)間了就喚醒消息隊(duì)列。
3.消息入隊(duì),通過(guò)調(diào)用handler的sendMessage方法,內(nèi)部是調(diào)用MessageQueue的enqueueMessage方法,進(jìn)行消息入隊(duì),入隊(duì)的規(guī)制是:隊(duì)列沒(méi)有消息,或者要入隊(duì)的消息沒(méi)有設(shè)置delay,或者delay時(shí)間比隊(duì)列頭的消息delay時(shí)間短,則將要入隊(duì)的消息放到隊(duì)列頭,否則就插到隊(duì)列中間,需要移動(dòng)鏈表。