消息机制总览Android中一切皆为消息,包括触摸事件和试图绘制机制,刷新,显示都是消息。
Handler机制
发送和处理消息。
Handler的创建
Handler()
Handler(Callback callback)
Handler(Looper looper)
Handler(Looper looper, Callback callback)
Handler(boolean async)
Handler(Callback callback, boolean async)
Handler(Looper looper, Callback callback, boolean async)
查询Handler构造方法源码可知,线程中使用Handler前要确保Looper不为null,否则报错(为什么子线程中new Handler()会报错?)
发送消息
sendMessage(Message msg)
post(Runnable r)
post(Runnable r)会调用getPostMessage(Runnable r, Object token)
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
//这两个参数后面分析会用到
m.obj = token;
m.callback = r;
return m;
}
Handler发送消息最终会调用MesageQueue.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对象===>Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Handler的销毁
最终会调用MessageQueue.removeCallbacksAndMessages
public final void removeCallbacksAndMessages(Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
Looper机制
从MessageQueue中循环取出消息。
Looper创建
prepare()
prepareMainLooper()//application’s main looper
private static void prepare(boolean quitAllowed) {
//每个线程只能有一个Looper对象
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//ThreadLocal通过ThreadLocalMap在指定线程中存取数据(感兴趣的伙伴自行了解一下)
sThreadLocal.set(new Looper(quitAllowed));
}
//Looper的构造器创建了MessageQueue对象
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread =
通过上述代码可以得出Handler:MessageQueue:Looper :Thread = N :1:1:1。
Looper的循环
public static void loop() {
...
for (;;) {
//next()方法是循环取出message,可能会阻塞()
Message msg = queue.next();
if (msg == null) {//什么时候msg会为null呢?
// No message indicates that the message queue is quitting.
return;
}
...
try {
//msg.target = Handler处理消息
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
//清洗message
msg.recycleUnchecked();
}
}
Looper通过loop()不断的从MessageQueue中取出消息,并执行dispatchMessage()。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {//msg.callback = Runnable。实际上回执行Runnable.run方法
handleCallback(msg);
} else {//mCallback = Handler中Callback接口
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//msg.callback跟Handler的Callback接口都不处理,就自己处理了涩
handleMessage(msg);
}
}
接着看一下msg.recycleUnchecked()
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
//Message Pool中Message最大为50
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
//通过obtain(),从MessagePool中取出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;
}
}
return new Message();
}
Message清洗后会存放到一个消息池中,方便以后取用,避免内存占用。
MessageQueue机制
MessageQueue的创建
Looper中已经提到MessageQueue的创建是在Looper中完成的。
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();//保存了c++层的MessageQueue对象
}
我们看一下nativeInit()的具体实现
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}
nativeMessageQueue->incStrong(env);
return reinterpret_cast(nativeMessageQueue);
}
nativeInit()最后创建了C++层MessageQueue对象并保存在mPtr中。通过这种方式将Java层对象和C++对象关联在一起。
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
创建一个C++层的Looper(与Java层没多大关系),并与当前线程绑定起来。
MessageQueue添加消息
boolean enqueueMessage(Message msg, long when) {
...
synchronized (this) {
...
msg.markInUse();
msg.when = when;
//mMessages:消息头
Message p = mMessages;
boolean needWake;
//消息头为null,或者当前等待时间为0或者当前等待时间小于消息头的时间
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 {//通过for循环添加Message并按照when的顺序进行排序
...
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;
//msg.next = p 和prev.next = msg相当于一个链表插入操作。(注意插入的位置一定不会是消息头)
}
// 唤醒等待线程,mPtr实际上是C++层的MessageQueue对象,nativePollOnce可能会使线程阻塞
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
通过上述方法我们知道,enqueueMessage会对添加其中的Message按照when排序。
MessageQueue获取Message
Message next() {
...
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//nextPollTimeOutMillis = -1,一直阻塞;nextPollTimeOutMillis = 0,不会阻塞,立即返回;nextPollTimeOutMillis>0最长阻塞时间,如果期间有程序唤醒立即返回
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;
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) {
//判断条件可以理解为msg.next.when < msg.when
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 {
// 一直阻塞
nextPollTimeoutMillis = -1;
}
//应用退出时Message才会出现null值
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
...
// 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;
}
}
消息为Null空时,会一直阻塞当前线程。
void removeCallbacksAndMessages(Handler h, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
//链表的末端
p = n;
}
}
}
recycleUnchecked()方法执行了两次这是为什么呢?
第一个循环是找到链表中的第一个消息;第二个循环遍历删除目标消息。
补充
HandlerThread
HandlerThread可以方便我们在工作线程中使用Handler(包含一个Looper)。
如何使用:
继承HandlerThread
通过new Handler(Looper looper)
网友评论