Handler是Android中非常重要的线程间通信方式,所以我们今天用生活中类似的情况来谈谈Handler。看下大概流程图。
Paste_Image.png
Message——信
数据类型 |
成员变量 |
解释 |
int |
what |
消息类别 |
long |
when |
消息触发时间 |
int |
arg1 |
参数1 |
int |
arg2 |
参数2 |
Object |
obj |
消息内容 |
Handler |
target |
消息目的地或者说处理者 |
Runnable |
callback |
回调方法 |
获取Message实例——obtain()
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;
}
}
return new Message();
}
MessageQueue——消息队列(邮箱)
MessageQueue在该机制中充当类似邮箱的角色,它从Handler中接收消息,然后等待Loop取走,这一过程中没有对消息有任何更改。下面介绍下主要变量和主要函数。
数据类型 |
成员变量 |
解释 |
boolean |
mQuitAllowed |
是否允许退出 |
Message |
mMessages |
消息队列,内部实现类似链表 |
boolean |
mQuitting |
是否已经退出 |
boolean |
mBlocked |
是否阻塞 |
long |
mPtr |
供native层方法使用 |
//native层方法
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis);
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
构造函数
MessageQueue(boolean quitAllowed) { //是否允许退出
mQuitAllowed = quitAllowed;
//通过native方法初始化消息队列,其中mPtr是供native代码使用
mPtr = nativeInit();
}
退出函数——quit(boolean safe)
void quit(boolean safe) {
// 当mQuitAllowed为false,表示不运行退出,强行调用quit()会抛出异常
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) { //防止多次执行退出操作
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked(); //移除尚未触发的所有消息
} else {
removeAllMessagesLocked(); //移除所有的消息
}
//唤醒消息队列,即从nativePollOnce()返回,使得next()可以往下执行
nativeWake(mPtr);
}
}
提取消息——next()
Message next() {
final long ptr = mPtr;
//如果已经调用quit()函数,直接返回
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; //循环迭代的首次为-1
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//阻塞操作,当等待nextPollTimeoutMillis时长,或者有新消息到达,都会退出该函数
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
//当消息Handler为空时,查询MessageQueue中的下一条异步消息msg,则退出循环。
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
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;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse(); //标记消息状态
return msg;
}
} else {
//没有消息
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;
}
//只有第一次进入循环时才进入下列循环 ps:pendingIdleHandlerCount = -1
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
//没有idle handlers 需要运行,则循环并等待。
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
//同样的,只有第一次循环时才下列循环,主要用于移除闲置的Handler
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null;
boolean keep = false; //标记Handler是否存活
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);//移除未保活的Handler
}
}
}
//设置空闲Handler数量为0,以保证不会再次重复运行
pendingIdleHandlerCount = 0;
//设置下次等待时长为0,以防在运行Handler时有新的消息到达
nextPollTimeoutMillis = 0;
}
}
存储消息——enqueueMessage(Message msg, long when)
boolean enqueueMessage(Message msg, long when) {
//如果message的targer或者说目的地为空,抛异常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//在退出时,回收msg,加入到消息池
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) {
//如果消息队列为空,或者新消息触发时间较早,加入消息队列
// New head, wake up the event queue if blocked.
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;
}
Looper——邮递员
Looper负责将MessageQueue中的消息分发给对应的Handler,如果MessageQueue中没有消息,则阻塞,直到MessageQueue中有新的消息,或者退出循环。
数据类型 |
成员变量 |
解释 |
ThreadLocal |
sThreadLocal |
类似Map,用于保存Looper实例 |
MessageQueue |
mQueue |
消息队列 |
构造函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed); //实例化消息队列
mThread = Thread.currentThread();
}
初始化函数——prepare()
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
//根据所在线程从ThreadLocal获取Looper实例,
// 注意,每个线程只能初始化一次
throw new RuntimeException("Only one Looper may be created per thread");
}
//根据所在线程保存Looper
sThreadLocal.set(new Looper(quitAllowed));
}
循环函数——loop()
public static void loop() {
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;
......
for (;;) {
//从消息队列获取消息,此时可能因为MessageQueue处于阻塞而被阻塞
Message msg = queue.next();
if (msg == null) {
//如果返回msg == null,则退出循环,
//我们可以通过调用某些方法使得返回的 msg 为 null,然后退出循环
return;
}
.......
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
//将msg 发送到目的地,并交给Handler处理
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
......
msg.recycleUnchecked(); //回收msg
}
}
退出——quit()
public void quit() {
//通过调用MessageQueue的quit(),使其返回null,进而退出循环
mQueue.quit(false);
}
Handler——寄信人/收信人
Handler扮演着既是寄信人,又是收信人的角色。
数据类型 |
成员变量 |
解释 |
Looper |
mLooper |
对应线程的Looper |
MessageQueue |
mQueue |
与mLooper相联系的消息队列 |
Callback(接口) |
mCallback |
用于处理消息的接口 |
构造函数
public Handler(Callback callback, boolean async) {
......
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException
("Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
写信——obtainMessage()
//从消息池中获取一条消息,并将target(目的地)设为自己
public final Message obtainMessage()
{
return Message.obtain(this);
}
寄信——sendMessageAtTime() & enqueueMessage()
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
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) {
msg.target = this;
if (mAsynchronous) { //是否是异步消息
msg.setAsynchronous(true);
}
//调用MessageQueue中的enqueueMessage(),将消息压入队列
return queue.enqueueMessage(msg, uptimeMillis);
}
public final boolean post(Runnable r)
{
//通过将Runnable包装成Message,并通过sendMessageAtTime方法发送
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
收信——dispatchMessage()
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) { //通过实现接口来实现处理方法
return;
}
}
handleMessage(msg); //待重写的处理方法
}
}
private static void handleCallback(Message message) {
message.callback.run(); //调用message自身的处理方法
}
/**
* 子类必须重写该方法才能对消息做相应的处理
*/
public void handleMessage(Message msg) {
}
Message——信
数据类型 |
成员变量 |
解释 |
int |
what |
消息类别 |
long |
when |
消息触发时间 |
int |
arg1 |
参数1 |
int |
arg2 |
参数2 |
Object |
obj |
消息内容 |
Handler |
target |
消息目的地或者说处理者 |
Runnable |
callback |
回调方法 |
获取Message实例——obtain()
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;
}
}
return new Message();
}
MessageQueue——消息队列(邮箱)
MessageQueue在该机制中充当类似邮箱的角色,它从Handler中接收消息,然后等待Loop取走,这一过程中没有对消息有任何更改。下面介绍下主要变量和主要函数。
数据类型 |
成员变量 |
解释 |
boolean |
mQuitAllowed |
是否允许退出 |
Message |
mMessages |
消息队列,内部实现类似链表 |
boolean |
mQuitting |
是否已经退出 |
boolean |
mBlocked |
是否阻塞 |
long |
mPtr |
供native层方法使用 |
//native层方法
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis);
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
构造函数
MessageQueue(boolean quitAllowed) { //是否允许退出
mQuitAllowed = quitAllowed;
//通过native方法初始化消息队列,其中mPtr是供native代码使用
mPtr = nativeInit();
}
退出函数——quit(boolean safe)
void quit(boolean safe) {
// 当mQuitAllowed为false,表示不运行退出,强行调用quit()会抛出异常
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) { //防止多次执行退出操作
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked(); //移除尚未触发的所有消息
} else {
removeAllMessagesLocked(); //移除所有的消息
}
//唤醒消息队列,即从nativePollOnce()返回,使得next()可以往下执行
nativeWake(mPtr);
}
}
提取消息——next()
Message next() {
final long ptr = mPtr;
//如果已经调用quit()函数,直接返回
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; //循环迭代的首次为-1
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//阻塞操作,当等待nextPollTimeoutMillis时长,或者有新消息到达,都会退出该函数
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
//当消息Handler为空时,查询MessageQueue中的下一条异步消息msg,则退出循环。
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
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;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse(); //标记消息状态
return msg;
}
} else {
//没有消息
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;
}
//只有第一次进入循环时才进入下列循环 ps:pendingIdleHandlerCount = -1
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
//没有idle handlers 需要运行,则循环并等待。
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
//同样的,只有第一次循环时才下列循环,主要用于移除闲置的Handler
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null;
boolean keep = false; //标记Handler是否存活
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);//移除未保活的Handler
}
}
}
//设置空闲Handler数量为0,以保证不会再次重复运行
pendingIdleHandlerCount = 0;
//设置下次等待时长为0,以防在运行Handler时有新的消息到达
nextPollTimeoutMillis = 0;
}
}
存储消息——enqueueMessage(Message msg, long when)
boolean enqueueMessage(Message msg, long when) {
//如果message的targer或者说目的地为空,抛异常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//在退出时,回收msg,加入到消息池
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) {
//如果消息队列为空,或者新消息触发时间较早,加入消息队列
// New head, wake up the event queue if blocked.
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;
}
Looper——邮递员
Looper负责将MessageQueue中的消息分发给对应的Handler,如果MessageQueue中没有消息,则阻塞,直到MessageQueue中有新的消息,或者退出循环。
数据类型 |
成员变量 |
解释 |
ThreadLocal |
sThreadLocal |
类似Map,用于保存Looper实例 |
MessageQueue |
mQueue |
消息队列 |
构造函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed); //实例化消息队列
mThread = Thread.currentThread();
}
初始化函数——prepare()
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
//根据所在线程从ThreadLocal获取Looper实例,
// 注意,每个线程只能初始化一次
throw new RuntimeException("Only one Looper may be created per thread");
}
//根据所在线程保存Looper
sThreadLocal.set(new Looper(quitAllowed));
}
循环函数——loop()
public static void loop() {
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;
......
for (;;) {
//从消息队列获取消息,此时可能因为MessageQueue处于阻塞而被阻塞
Message msg = queue.next();
if (msg == null) {
//如果返回msg == null,则退出循环,
//我们可以通过调用某些方法使得返回的 msg 为 null,然后退出循环
return;
}
.......
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
//将msg 发送到目的地,并交给Handler处理
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
......
msg.recycleUnchecked(); //回收msg
}
}
退出——quit()
public void quit() {
//通过调用MessageQueue的quit(),使其返回null,进而退出循环
mQueue.quit(false);
}
Handler——寄信人/收信人
Handler扮演着既是寄信人,又是收信人的角色。
数据类型 |
成员变量 |
解释 |
Looper |
mLooper |
对应线程的Looper |
MessageQueue |
mQueue |
与mLooper相联系的消息队列 |
Callback(接口) |
mCallback |
用于处理消息的接口 |
构造函数
public Handler(Callback callback, boolean async) {
......
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException
("Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
写信——obtainMessage()
//从消息池中获取一条消息,并将target(目的地)设为自己
public final Message obtainMessage()
{
return Message.obtain(this);
}
寄信——sendMessageAtTime() & enqueueMessage()
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
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) {
msg.target = this;
if (mAsynchronous) { //是否是异步消息
msg.setAsynchronous(true);
}
//调用MessageQueue中的enqueueMessage(),将消息压入队列
return queue.enqueueMessage(msg, uptimeMillis);
}
public final boolean post(Runnable r)
{
//通过将Runnable包装成Message,并通过sendMessageAtTime方法发送
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
收信——dispatchMessage()
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) { //通过实现接口来实现处理方法
return;
}
}
handleMessage(msg); //待重写的处理方法
}
}
private static void handleCallback(Message message) {
message.callback.run(); //调用message自身的处理方法
}
/**
* 子类必须重写该方法才能对消息做相应的处理
*/
public void handleMessage(Message msg) {
}
总结
- Handler通过sendMessage向MessageQueue发送消息
- Looper通过Loop不断向MessageQueue提取消息,没有消息时会阻塞
- Looper通过将提取到的Message交给target处理
参考资料
Android消息机制1-Handler(Java层)
网友评论