Handler詳解
舉例
- 線程間傳遞數(shù)據(jù)(主線程跟子線程俯邓、兩個(gè)子線程)
簡(jiǎn)介
- 一套android消息傳遞機(jī)制梦皮。在多線程的應(yīng)用場(chǎng)景中芹缔,將工作線程中需更新UI的操作信息傳遞到 UI主線程驾孔,從而實(shí)現(xiàn)工作線程對(duì)UI的更新處理秋度,最終實(shí)現(xiàn)異步消息的處理炸庞。
- 使用Handler的原因:將工作線程需操作UI的消息傳遞到主線程,使得主線程可根據(jù)工作線程的需求更新UI荚斯,從而避免線程操作不安全的問(wèn)題
工作流程
- 異步通信準(zhǔn)備
- 在主線程中創(chuàng)建處理器對(duì)象(Looper)埠居、消息隊(duì)列對(duì)象(MessageQueue)、Handler對(duì)象
- 消息入隊(duì)
- 工作線程通過(guò)Handler發(fā)送消息(Message)到消息隊(duì)列(MessageQueue)中
- 消息循環(huán)
- 消息出隊(duì):Looper循環(huán)取出消息隊(duì)列(MessageQueue)中的消息(Message)
- 消息分發(fā):Looper將取出的消息(Message)發(fā)送給創(chuàng)建該消息的處理者(Handler)
- 消息處理
- 處理者(Handler)接受處理器(Looper)發(fā)送過(guò)來(lái)的消息(Message)
-
處理者(Handler)根據(jù)消息(Message)進(jìn)行UI操作
核心類
源碼分析
- 創(chuàng)建Handler
//在主線程中 通過(guò)匿名內(nèi)部類創(chuàng)建Handler類對(duì)象
private Handler mhandler = new Handler(){
// 通過(guò)復(fù)寫handlerMessage()從而確定更新UI的操作
@Override
public void handleMessage(Message msg) {
// 需執(zhí)行的UI操作
...
}
};
//創(chuàng)建消息對(duì)象
Message message = handler.obtainMessage(MESSAGE_WHAT);
message.obj = "I am message from work thread";
//發(fā)送
handler.sendMessage(message);
/**
* 源碼分析:Handler的構(gòu)造方法
* 作用:初始化Handler對(duì)象 & 綁定線程
* a. Handler需綁定線程才能使用事期;綁定后拐格,Handler的消息處理會(huì)在綁定的線程中執(zhí)行
* b. 綁定方式為先指定Looper對(duì)象,從而綁定了Looper對(duì)象所綁定的線程(因?yàn)長(zhǎng)ooper對(duì)象本已綁定了對(duì)應(yīng)線程)刑赶,即指定了Handler對(duì)象的Looper對(duì)象綁定到了Looper對(duì)象所在的線程
*/
public Handler() {
this(null, false);
}
/**
* 分析:this(null, false) = Handler(null捏浊,false)
*/
public Handler(Callback callback, boolean async) {
// 1、 指定Looper對(duì)象
// 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ì)象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 2、綁定消息隊(duì)列對(duì)象(MessageQueue),獲取該Looper對(duì)象中保存的消息隊(duì)列對(duì)象(MessageQueue)胡岔,保證了handler對(duì)象關(guān)聯(lián)上Looper對(duì)象中MessageQueue
mQueue = mLooper.mQueue;
}
- 創(chuàng)建主線程時(shí)法希,會(huì)自動(dòng)調(diào)用ActivityThread的1個(gè)靜態(tài)的main();而main()內(nèi)則會(huì)調(diào)用Looper.prepareMainLooper()為主線程生成1個(gè)Looper對(duì)象靶瘸,同時(shí)也會(huì)生成其對(duì)應(yīng)的MessageQueue對(duì)象
//主線程(ActivityThread)創(chuàng)建Looper對(duì)象和對(duì)應(yīng)的消息隊(duì)列對(duì)象(MessageQueue)
public static void main(String[] args) {
//為主線程創(chuàng)建1個(gè)Looper對(duì)象苫亦,同時(shí)生成1個(gè)消息隊(duì)列對(duì)象(MessageQueue),該方法在主線程(UI線程)創(chuàng)建時(shí)自動(dòng)調(diào)用,即主線程的Looper對(duì)象自動(dòng)生成怨咪,不需手動(dòng)生成
Looper.prepareMainLooper();
//創(chuàng)建主線程
ActivityThread thread = new ActivityThread();
//自動(dòng)開(kāi)啟 消息循環(huán)
Looper.loop();
}
/**
* 分析:prepareMainLooper()
*/
public static void prepareMainLooper() {
prepare(false);
//主線程只能有一個(gè)looper
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
* 分析:prepare(false)
*/
private static void prepare(boolean quitAllowed) {
// 判斷sThreadLocal是否為null屋剑,否則拋出異常
//即 Looper.prepare()方法不能被調(diào)用兩次,1個(gè)線程中只能對(duì)應(yīng)1個(gè)Looper實(shí)例
//注:sThreadLocal是ThreadLocal(線程本地存儲(chǔ)區(qū))對(duì)象诗眨,用于保存線程共享變量
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* 分析:Looper()
*/
private Looper(boolean quitAllowed) {
//生成消息隊(duì)列(MessageQueue,綁定對(duì)應(yīng)線程)
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
- 創(chuàng)建消息對(duì)象
Message message = handler.obtainMessage(MESSAGE_WHAT);
message.obj = "I am message from work thread";
/**
* 分析:handler.obtainMessage(MESSAGE_WHAT);
* 作用:創(chuàng)建消息對(duì)象
* 注:創(chuàng)建Message對(duì)象可用關(guān)鍵字new 或 Message.obtain()
*/
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
}
public static Message obtain() {
// Message內(nèi)部維護(hù)了1個(gè)Message池唉匾,用于Message消息對(duì)象的復(fù)用
// 使用obtain()則是直接從池內(nèi)獲取
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
// 建議使用obtain()創(chuàng)建消息對(duì)象,避免每次都使用new重新分配內(nèi)存
}
// 若池內(nèi)無(wú)消息對(duì)象可復(fù)用匠楚,則還是用關(guān)鍵字new創(chuàng)建
return new Message();
}
- 發(fā)送消息
mHandler.sendMessage(msg);
或者
handler.post(new Runnable() {
@Override public void run() {
...
}
});
/**
* 分析:sendMessage(Message msg)
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
/**
* 分析:post(Runnable r)
*/
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
/**
* 分析:getPostMessage(r)
* 作用:將傳入的Runable對(duì)象封裝成1個(gè)消息對(duì)象
*/
private static Message getPostMessage(Runnable r) {
//創(chuàng)建1個(gè)消息對(duì)象(Message)
Message m = Message.obtain();
//將Runable對(duì)象賦值給消息對(duì)象(message)的callback屬性
m.callback = r;
//返回該消息對(duì)象
return m;
}
/**
* 分析:sendMessageDelayed(msg, 0)
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/**
* 分析sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
// 1. 獲取對(duì)應(yīng)的消息隊(duì)列對(duì)象(MessageQueue)
MessageQueue queue = mQueue;
// 2. 調(diào)用了enqueueMessage方法
return enqueueMessage(queue, msg, uptimeMillis);
}
/**
* 分析:enqueueMessage(queue, msg, uptimeMillis)
*/
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 1. 將msg.target賦值為this,即把當(dāng)前的Handler實(shí)例對(duì)象作為msg的target屬性
msg.target = this;
// 2. 調(diào)用消息隊(duì)列的enqueueMessage()巍膘,即:Handler發(fā)送的消息,最終是保存到消息隊(duì)列
return queue.enqueueMessage(msg, uptimeMillis);
}
/**
* 定義:屬于消息隊(duì)列類(MessageQueue)的方法
* 作用:入隊(duì)芋簿,即將消息根據(jù)時(shí)間放入到消息隊(duì)列中(Message ->> MessageQueue)
* 采用單鏈表實(shí)現(xiàn):提高插入消息峡懈、刪除消息的效率
*/
boolean enqueueMessage(Message msg, long when) {
...// 僅貼出關(guān)鍵代碼
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 判斷消息隊(duì)列里有無(wú)消息
// a. 若無(wú),則將當(dāng)前插入的消息作為隊(duì)頭,若此時(shí)消息隊(duì)列處于等待狀態(tài)与斤,則喚醒
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;
// b. 判斷消息隊(duì)列里有消息逮诲,則根據(jù)消息(Message)觸發(fā)的時(shí)間插入到隊(duì)列中
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;
}
- Looper從消息隊(duì)列取消息并分發(fā)給Handler
/**
* 源碼分析: Looper.loop()
* 作用:消息循環(huán),即從消息隊(duì)列中獲取消息幽告、分發(fā)消息到Handler
*/
public static void loop() {
...// 僅貼出關(guān)鍵代碼
// 獲取當(dāng)前Looper的消息隊(duì)列梅鹦,myLooper()作用:返回sThreadLocal存儲(chǔ)的Looper實(shí)例;若me為null 則拋出異常冗锁,即loop()執(zhí)行前必須執(zhí)行prepare()齐唆,從而創(chuàng)建1個(gè)Looper實(shí)例
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 獲取Looper實(shí)例中的消息隊(duì)列對(duì)象(MessageQueue)
final MessageQueue queue = me.mQueue;
// 消息循環(huán)
for (;;) {
//從消息隊(duì)列中取出消息,next():取出消息隊(duì)列里的消息冻河,若取出的消息為空箍邮,則線程阻塞
Message msg = queue.next();
if (msg == null) {
return;
}
// 派發(fā)消息到對(duì)應(yīng)的Handler,把消息Message派發(fā)給消息對(duì)象msg的target屬性叨叙,target屬性實(shí)際是1個(gè)handler對(duì)象
msg.target.dispatchMessage(msg);
// 釋放消息占據(jù)的資源
msg.recycleUnchecked();
}
}
/**
* 分析:queue.next()
* 定義:屬于消息隊(duì)列類(MessageQueue)中的方法
* 作用:出隊(duì)消息锭弊,即從 消息隊(duì)列中 移出該消息
*/
Message next() {
...// 僅貼出關(guān)鍵代碼
// 該參數(shù)用于確定消息隊(duì)列中是否還有消息,從而決定消息隊(duì)列應(yīng)處于出隊(duì)消息狀態(tài) or 等待狀態(tài)
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// nativePollOnce方法在native層擂错,若是nextPollTimeoutMillis為-1味滞,此時(shí)消息隊(duì)列處于等待狀態(tài)
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// 出隊(duì)消息,即從消息隊(duì)列中取出消息:按創(chuàng)建Message對(duì)象的時(shí)間順序
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 取出了消息
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
msg.markInUse();
return msg;
}
} else {
// 若 消息隊(duì)列中已無(wú)消息,則將nextPollTimeoutMillis參數(shù)設(shè)為-1
// 下次循環(huán)時(shí)剑鞍,消息隊(duì)列則處于等待狀態(tài)
nextPollTimeoutMillis = -1;
}
......
}
.....
}
}
/**
* 分析:dispatchMessage(msg)
* 定義:屬于處理者類(Handler)中的方法
* 作用:派發(fā)消息到對(duì)應(yīng)的Handler實(shí)例 & 根據(jù)傳入的msg作出對(duì)應(yīng)的操作
*/
public void dispatchMessage(Message msg) {
// 若msg.callback屬性不為空昨凡,則代表使用了post(Runnable r)發(fā)送消息,則執(zhí)行handleCallback(msg)蚁署,即回調(diào)Runnable對(duì)象里復(fù)寫的run()
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 若msg.callback屬性為空便脊,則代表使用了sendMessage(Message msg)發(fā)送消息,則執(zhí)行handleMessage(msg)光戈,即回調(diào)復(fù)寫的handleMessage(msg)
handleMessage(msg);
}
}
/**
* 分析:handleMessage(msg)
* 在創(chuàng)建Handler實(shí)例時(shí)復(fù)寫
*/
public void handleMessage(Message msg) {
... // 創(chuàng)建Handler實(shí)例時(shí)復(fù)寫
}
- MessageQueue native中nativeWake(long ptr)跟nativePollOnce(long ptr, int timeoutMillis)
/**
* 分析:android_os_MessageQueue.cpp中nativeWake(long ptr)
*/
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->wake();
}
/**
* 指向了Looper.cpp的wake()
*/
void NativeMessageQueue::wake() {
mLooper->wake();
}
/**
* Looper.cpp中wake()
*/
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ wake", this);
#endif
ssize_t nWrite;
do {
// 向管道m(xù)WakeWritePipeFd寫入字符哪痰,用來(lái)喚醒線程
nWrite = write(mWakeWritePipeFd, "W", 1);
} while (nWrite == -1 && errno == EINTR);
if (nWrite != 1) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
}
}
/**
* 分析:android_os_MessageQueue.cpp中nativePollOnce(long ptr, int timeoutMillis)
*/
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
/**
* 指向了Looper.cpp中的pollOnce()
*/
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
mLooper->pollOnce(timeoutMillis);
mPollObj = NULL;
mPollEnv = NULL;
if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
/**
* Looper.cpp中pollOnce
*/
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
// 先處理沒(méi)有Callback方法的 Response事件
while (mResponseIndex < mResponses.size()) {
const Response& response = mResponses.itemAt(mResponseIndex++);
int ident = response.request.ident;
if (ident >= 0) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE
if (outFd != NULL) *outFd = fd;
if (outEvents != NULL) *outEvents = events;
if (outData != NULL) *outData = data;
return ident;
}
}
if (result != 0) {
if (outFd != NULL) *outFd = 0;
if (outEvents != NULL) *outEvents = 0;
if (outData != NULL) *outData = NULL;
return result;
}
//處理內(nèi)部輪詢
result = pollInner(timeoutMillis);
}
}
/**
* pollInner(int timeoutMillis)
*/
int Looper::pollInner(int timeoutMillis) {
// 調(diào)整超時(shí)時(shí)間根據(jù)下一條消息
if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
if (messageTimeoutMillis >= 0
&& (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
timeoutMillis = messageTimeoutMillis;
}
int result = ALOOPER_POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
//等待事件發(fā)生或者超時(shí),向管道寫端寫入字符久妆,則該方法會(huì)返回
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// Acquire lock.
mLock.lock();
// Check for poll error.
if (eventCount < 0) {
if (errno == EINTR) {
goto Done;
}
result = ALOOPER_POLL_ERROR;
goto Done;
}
// Check for poll timeout.
if (eventCount == 0) {
result = ALOOPER_POLL_TIMEOUT;
goto Done;
}
// 循環(huán)遍歷晌杰,處理所有的事件
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
//通過(guò)管道讀端被喚醒
if (fd == mWakeReadPipeFd) {
if (epollEvents & EPOLLIN) {
//去把管道數(shù)據(jù)中數(shù)據(jù)讀完
awoken();
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
}
} else {
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
//處理request,生成對(duì)應(yīng)的respone對(duì)象,push到響應(yīng)數(shù)組
pushResponse(events, mRequests.valueAt(requestIndex));
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
Done: ;
// 再處理Native的Message镇饺,調(diào)用相應(yīng)回調(diào)方法
mNextMessageUptime = LLONG_MAX;
while (mMessageEnvelopes.size() != 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
if (messageEnvelope.uptime <= now) {
{ // obtain handler
sp<MessageHandler> handler = messageEnvelope.handler;
Message message = messageEnvelope.message;
mMessageEnvelopes.removeAt(0);
mSendingMessage = true;
mLock.unlock();
handler->handleMessage(message);
} // release handler
mLock.lock();
mSendingMessage = false;
result = ALOOPER_POLL_CALLBACK;
} else {
// The last message left at the head of the queue determines the next wakeup time.
mNextMessageUptime = messageEnvelope.uptime;
break;
}
}
// Release lock.
mLock.unlock();
//處理帶有Callback()方法的Response事件乎莉,執(zhí)行Reponse相應(yīng)的回調(diào)方法
for (size_t i = 0; i < mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident == ALOOPER_POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
int callbackResult = response.request.callback->handleEvent(fd, events, data);
if (callbackResult == 0) {
removeFd(fd);
}
//清除reponse引用的回調(diào)方法
response.request.callback.clear();
result = ALOOPER_POLL_CALLBACK;
}
}
return result;
}
/**
* 讀取管道數(shù)據(jù)
*/
void Looper::awoken() {
char buffer[16];
ssize_t nRead;
do {
nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
}
總結(jié)
- 應(yīng)用程序主線程創(chuàng)建時(shí)送讲,則自動(dòng)為主線程
- 創(chuàng)建一個(gè)處理器對(duì)象Looper
- 創(chuàng)建消息隊(duì)列對(duì)象(MessageQueue)
- 進(jìn)入消息循環(huán)
- 創(chuàng)建Handler實(shí)例奸笤,綁定所在的當(dāng)前線程和對(duì)應(yīng)的消息隊(duì)列
- 創(chuàng)建消息對(duì)象(Message、Runnable)
- 隨著Looper對(duì)象的無(wú)限消息循環(huán)哼鬓,從消息隊(duì)列(MessageQueue)中取出Handler發(fā)送的消息监右,不斷將消息發(fā)送到對(duì)應(yīng)的Handler,根據(jù)回調(diào)方法進(jìn)行相關(guān)的處理。