android 消息机制一直只是使用而没有理解它原理,此篇将分析其原理。
什么是android消息机制? 一句话:一个线程无限循环监听并依次处理其他线程的消息,没有消息就释放资源休眠。
android消息机制主要类:
1. handler : 处理者,处理消息 。
2. message : 消息,存放信息的载体 。
3. messageQueue : 消息队列,存放 message 的队列 。
4. looper : 消息循环者,循环从 messageQueue 拿出 message 给 handler 处理 。
它们之间的关系:
handler 发送 message 到 messageQueue , messageQueue 有序将 message 装好, looper 循环从 messageQueue 中拿到 message 交给 hanlder 处理。
handler 发送消息
首先看它的模拟例子
// 新启动一个子线程 new Thread(new Runnable() { @Override public void run() { // tv.setText("..."); // 以上操作会报错,无法再子线程中访问UI组件,UI组件的属性必须在UI线程中访问 // 使用post方式修改UI组件tvMessage的Text属性 handler.post(new Runnable() { @Override public void run() { tv.setText("使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。"); } }); } }).start();
而后我们看它的构造方法
public class Handler { }
public Handler() { this(null, false); }
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {//检测匿名, 本地 , 或成员类是否内存泄露,默认 false ,建议用 static
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());
}
}
mLooper = Looper.myLooper();//得到looper
if (mLooper == null) {//判断looper是否为 null , 为 null抛异常
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//不为null,赋值 MessageQueue mQueue , Callback mCallback , boolean mAsynchronous
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
而后看它发送消息的方法
post
发送消息到消息队列 public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0); }
在某个时间发送消息到消息队列 public final boolean postAtTime(Runnable r, long uptimeMillis){ return sendMessageAtTime(getPostMessage(r), uptimeMillis); }
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis){ return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); }
延时发送消息到消息队列 public final boolean postDelayed(Runnable r, long delayMillis){ return sendMessageDelayed(getPostMessage(r), delayMillis); }
发送消息到消息队列前端 public final boolean postAtFrontOfQueue(Runnable r){ return sendMessageAtFrontOfQueue(getPostMessage(r)); }
send
发送消息到消息队列 public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0); }
发送空消息到消息队列 public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0); }
延时发送空消息到消息队列 public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); }
在某个时候发送空消息到消息队列 public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); }
延时发送消息到消息队列 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) { 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); }
发送消息到消息队列前端 public final boolean sendMessageAtFrontOfQueue(Message msg) { 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, 0); }
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
可以看出 handler 发送消息的步骤为:
post () > sendMessageDelayed () > sendMessageAtTtime() > equeueMessage()
handler 最终调用 equeueMessage() 而调用messageQueue 的 enqueueMessage() 将 message 放进 messageQueue 中
handler 发送消息总结 :
Message
public final class Message implements Parcelable { }
首先看它的重要成员变量
public int what; 消息标识 public int arg1; 消息数据1 public int arg2; 消息数据2 public Object obj; 消息内容实体 Handler target; 消息响应方 Runnable callback; 回调 Message sPool; 消息池消息 Message next;下个消息
message 里有一个 message pool ( 消息池 ) 这个概念,单链表结构写法是 message 优化,可以学学。
message里面没有构造方法,但是有obtian()
public static Message obtain() { synchronized (sPoolSync) {加锁 if (sPool != null) { 判断消息池消息对象是否为空 Message m = sPool; 将消息池消息赋值给局部变量 m sPool = m.next; 将局部变量 m 的下个消息 赋值给 消息池消息 m.next = null; 将布局变量 m 的 下个消息为 null m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); 返回新 message }
这个方法是为了 message 维护 message pool 重复使用 message , 避免分配新对象
消息池默认 size为 50 ,
private static final int MAX_POOL_SIZE = 50;
message回收
public void recycle() { if (isInUse()) { 是否正在使用 if (gCheckRecycle) { 是否gc throw new IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } 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; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; 把当前 message 赋值给消息池消息对象 sPoolSize++; } } }
所以使用 message 可以 new message,但是不提倡 , 应该使用 Message.obtain()。
MessageQueue
messageQueue 主要看两个操作:插入 和 读取。前面说了 handler 发送message最终调用了 messageQueue.enqueueMessage() 。现在我们来看看 enqueueMessage() 方法 (插入)。
boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { 判断 Handler target 是否为 null throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) { 判断 message 是否 throw new IllegalStateException(msg + " This message is already in use."); } 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) { 如果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 (;;) { 无限循环,链表操作按 message when 消息时间排序 prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; 唤醒事件队列标识为 false } } msg.next = p; // invariant: p == prev.next prev.next = msg; } if (needWake) { nativeWake(mPtr); 唤醒事件队列 } } return true; }
message 在 enqueueMessage() 中是以时间顺序排序,按先进先出顺序处理
下面看 next()
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration 等待闲置的handler个数
int nextPollTimeoutMillis = 0; 下个检查超时时间
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands(); binder 刷新等待命令,释放资源
}
nativePollOnce(ptr, nextPollTimeoutMillis); 检查一次
nativePollOnce()返回后执行
synchronized (this) { 加锁同步
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
找到下个message
if (msg != null && msg.target == null) {
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. 没有消息,下次检查超时时间为 -1
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled. 判断队列是否退出
if (mQuitting) {
dispose(); 销毁队列
return null;
}
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size(); 得到闲置handler数量
}
if (pendingIdleHandlerCount <= 0) {.
mBlocked = true; 将 阻塞标识 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; // 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); 移除闲置handler
}
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}
next() 从 messageQueue 的头部取出下一个 message , 如果没有 message , 则处理 idleHandler(等待的handler) 里的
message。 所以 一个messageQueue 对应多个 handler 可以,一个handler也可以发送多个message个。
looper
looper重要全员变量
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 线程共享类, private static Looper sMainLooper; // guarded by Looper.class 主线程 final MessageQueue mQueue; 消息队列 final Thread mThread; 线程
ThreadLocal 是用 类似map 保存线程变量
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }最后找到 ThreadLocalMap 中的 Entry,就明了了
static class Entry extends WeakReference<ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
现在看looper构造方法
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); 得到MessageQueue实例 mThread = Thread.currentThread(); 创建线程 }
然后看prepare(),将 ThreadLocal 作为 key , looper作为 value
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
然后看loop()
public static void loop() { final Looper me = myLooper(); 得到当前looper if (me == null) { 判断looper me 是否为 null ,为null 抛出异常 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; 得到当前looper 的 MessageQueue Binder.clearCallingIdentity(); 清除线程调用标识 final long ident = Binder.clearCallingIdentity(); 得到本地线程标识 无限循环 for (;;) { Message msg = queue.next(); 得到message if (msg == null) { return; } final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); final long end; try { msg.target.dispatchMessage(msg); 交给handler 处理 messaege end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (slowDispatchThresholdMs > 0) { final long time = end - start; if (time > slowDispatchThresholdMs) { Slog.w(TAG, "Dispatch took " + time + "ms on " + Thread.currentThread().getName() + ", h=" + msg.target + " cb=" + msg.callback + " msg=" + msg.what); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); 回收资源 } }
得到 Looper
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
得到MessageQueue
public static @NonNull MessageQueue myQueue() { return myLooper().mQueue; }
lopper 是调用 myLooper() ,Looper me.mQueue 拿到 messageQueue , 用 messageQueue queue.next() 得到 message,
最后调用 dispatchMessage() 把 message 交给 handler处理
msg.target.dispatchMessage(msg);
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
当 msg.callback != null , 就回调 Runable 里的 run() 方法,做异步处理
private static void handleCallback(Message message) { message.callback.run(); }
否则,回调 mCallback 的 handlerMessage()方法 或 调用自己的 handlerMessage(), 做异步处理
public interface Callback { public boolean handleMessage(Message msg); }
public void handleMessage(Message msg) { }
好了到此Android消息机制就全部介绍完毕了,喜欢请点个赞。
最后推荐其他handler机制好文章
http://www.cnblogs.com/jycboy/p/5786551.html
https://www.jianshu.com/p/02962454adf7