一、使用詳解
(1)Handler使用
//創建一個帶有Looper的線程
class LooperThread extends Thread{
@Override
public void run() {
Looper.prepare();
Looper.loop();
}
}
//在主線程中創建,自動綁定主線程Looper
private Handler uiHandler = new Handler() {
//重寫Handler的處理消息的方法handleMessage()
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
break;
}
}
};
//獲取子線程實例
LooperThread looperThread = new LooperThread();
//開啟子線程
looperThread.start();
//獲取子線程Looper
Looper loop = looperThread .getLooper();
//手動綁定子線程Looper
private Handler mHandler = new Handler(loop) {
//重寫Handler的處理消息的方法handleMessage()
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
break;
}
}
};
//發送消息
Message message = new Message();
message.what = 1;
message.obj = "result";
uiHandler.sendMessage(message )
mHandler.sendMessage(message )
(2)Handler構造方法
- Handler():構造函數將通過調用Looper.myLooper()獲取當前線程綁定的Looper對象,將該Looper對象保存到名為mLooper的成員字段中。
- Handler(Looper looper):直接將該Looper保存到名為mLooper的成員字段中。
- Handler(Callback callback):構造函數傳遞了Callback對象,Callback是Handler中的內部接口,需要實現其內部的handleMessage方法。
- Handler(Looper looper, Callback callback)
處理Message消息,通過實現Handler.Callback的handleMessage方法或重寫Handler本身的handleMessage方法
多線程實現:向Thread的post函數傳入一個Runnable對象者重寫Thread本身的run方法。
二、源碼解析
(1)Handler源碼
Handler的創建
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//獲取當前線程的Looper對象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//獲取當前Looper的消息隊列MessageQueue對象
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
Handler.sendMessage發送消息
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//Handler所綁定的消息隊列MessageQueue
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(MessageQueue queue, Message msg, long uptimeMillis) {
//將Message的target綁定為當前的Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//通過queue.enqueueMessage(msg, uptimeMillis)我們將Message放入到消息隊列中。
return queue.enqueueMessage(msg, uptimeMillis);
}
Handler.dispatchMessage發送消息到Handler
//派發消息到對應的Handler實例。根據傳入的msg作出對應的操作
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//使用了post發送消息,則執行handleCallback方法,回調Runnable復寫的run方法
handleCallback(msg);
} else {
//使用了sendMessage發送消息,則執行handleMessage,回調復寫的handleMessage
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
(2)Looper創建源碼
Looper.prepare()創建Looper,當前線程和Looper就進行了雙向的綁定
//Looper對象中通過sThreadLocal就可以找到其綁定的線程
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//1個線程中只能對應1個Looper實例
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//創建Looper對象存放在ThreadLocal變量中
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
//創建消息隊列對象
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper.loop()循環獲取MessageQueue中消息Message
public static void loop() {
//獲取當前線程所綁定的Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//獲取當前線程所關聯的消息隊列
final MessageQueue queue = me.mQueue;
//code...
//消息循環
for (;;) {
//從消息隊列中取出消息
Message msg = queue.next(); // might block
//若取出的消息為空,則線程阻塞
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
//code...
try {
//Message所關聯的Handler通過dispatchMessage方法讓Handler處理該Message
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//code...
//釋放消息占據的資源
msg.recycleUnchecked();
}
}
Looper類還提供了一些有用的方法
//獲取當前線程的Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
//獲取looper對象所屬線程
public Thread getThread() {
return mThread;
}
//結束looper循環
public void quit() {
// 創建一個空的message,它的target為NULL,表示結束循環消息
Message msg = Message.obtain();
// 發出消息
mQueue.enqueueMessage(msg, 0);
}
(3)MessageQueue源碼
MessageQueue.enqueueMessage將一個Message放入到消息隊列MessageQueue中
boolean enqueueMessage(Message msg, long when) {
//code...
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//判斷消息隊列里有無消息
if (p == null || when == 0 || when < p.when) {
//消息隊列無消息將當前插入的消息作為隊頭,若此時消息隊列處于等待狀態,則喚醒
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//消息隊列里有消息,則根據消息創建的時間 插入到隊列中
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
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;
}
MessageQueue.next從消息隊列MessageQueue中阻塞式地取出一個Message
Message next() {
//code...
//確定消息隊列中是否還有消息。從而決定消息隊列應處于出隊消息狀態還是等待狀態
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//若是nextPollTimeoutMillis為-1,此時消息隊列處于等待狀態
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;
//從消息隊列中取出消息:按創建Message對象的時間順序
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) {
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.
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.
//消息隊列中已無消息,則將nextPollTimeoutMillis參數設為-1。下次循環時,消息隊列則處于等待狀態
nextPollTimeoutMillis = -1;
}
//code...
}
//code...
}
}
(4)Message源碼
//Message內部維護了一個Message池,用于Message消息對象的復用
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
//若池內無消息對象可復用,則還是用關鍵字new創建
return new Message();
}