一,概要
Android 应用是基于事件驱动的,每个事件(UI绘制、滑动等)都会转化为一个系统消息,即 Message。然后,系统 looper 通过维护一个消息队列 messageQueue 来完成消息的分发处理.
二,介绍
1.Message( 快递)
public final class Message implements Parcelable {
/*package*/ static final int FLAG_IN_USE = 1 << 0;
/** If set message is asynchronous */
/*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
/** Flags to clear in the copyFrom method */
/*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
/*package*/ int flags;
/*package*/ Handler target;
/*package*/ Runnable callback;
// sometimes we store linked lists of these things
/*package*/ Message next;
}
message 是handler机制中的最小单位。(我们看下,我们比较陌生的成员变量 和方法)
1.target:是发送和处理该 message 的handler
2. callback:即是我们post的 Runnable。可以理解,我们的message 有两种:1.传递数据 ,2.一种是传递Runnable 接口
3.flags: 是message 的一种标识:
FLAG_ASYNCHRONOUS(同步) FLAG_IN_USE(使用中) FLAGS_TO_CLEAR_ON_COPY_FROM(清除标记)
4. next : 指向下一个message (message 是 基于链表结构 )
5 .static Message obtain():获取message方法:
public static Message obtain() {
//sPoolSync 线程同步对象锁
synchronized (sPoolSync) {
//sPool (message 静态变量,message消息列表的根节点)
if (sPool != null) {
//将根节点,赋给变量m
Message m = sPool;
//根节点指向下一个message
sPool = m.next;
//变量m 的下一个message指向null,把m 从链表完全割离
m.next = null;
m.flags = 0; // clear in-use flag
//链表长度减一
sPoolSize--;
return m;
}
}
//如果初始时候,链表为空,则新建一个message
return new Message();
}
6. public void recycleUnchecked() :释放回收message方法
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it"is still in use.");
}
return;
}
recycleUnchecked();
}
//message 成员变量置为空
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) {
//MAX_POOL_SIZE message 默认的最大容量
if (sPoolSize < MAX_POOL_SIZE) {
//当前message 的 next 指向了 message列表头部
next = sPool;
//成功将回收释放的message 插到列表头部
sPool = this;
//数量++
sPoolSize++;
}
}
}
因此,我们在使用message 的时候,尽量要用obtain() 而不是 new Message(), 这样可以 复用对象,避免多次创建对象,导致内存的增长
2.MessageQueue(传送带)
1.boolean enqueueMessage(Message msg, long when) :向 message 链表 中加入新的message
boolean enqueueMessage(Message msg, long when) {
//如果message 没有 持有handler
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) {
//如果messagequeue 所在 线程死亡,queue 中的message 回收
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;
//mMessages 标记最近的一个 message
Message p = mMessages;
boolean needWake;
//如果 mMessages 为null, 直接将添加的新消息插入链表头部
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;
//轮询message列表,插入链表中
for (;;) {
prev = p;
p = p.next;
//如果加入的message 时间小于 p 的时间
if (p == null || when < p.when) {
break;
}
//需要唤醒,且p 是异步 message
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//插入p(message) 的前面
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
//native 层 唤醒方法
nativeWake(mPtr);
}
}
return true;
2.Message next() : 获取下一个 message
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
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());
}
//普通我们发的消息为异步消息,只会走到这个方法(target 不会为null,Asynchronous且为 false)
// mMessage 赋给 msg 返回, mMessage 并指向 mMessage 的下一个message ,
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;
}
}
从源码可知,messageQueue 负责 将新的 message 加入链表,和取出链表
3.Looper(快递公司)
1.一个线程中有几个looper?
2.主线程 和 子线程 中使用的注意事项
public final class Looper {
private static final String TAG = "Looper";
//thread 所持有 副本对象 ThreadLocal(涉及到Java 并发,后期会说下)
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//主线程的looper
private static Looper sMainLooper;
//looper 所持有的 MessageQueue
final MessageQueue mQueue;
//looper 所在的线程
final Thread mThread;
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
1.从 中构造函数中,可以看到,looper 维持着一个线程 和 一个 MessageQueue()
2.私有的构造函数,如果使用的时候,怎么获取的,所以我们找一找它的其它的 替代方法。
private static void prepare(boolean quitAllowed)
public static void prepareMainLooper()
1.private static void prepare(boolean quitAllowed) 创建主线程 looper
public final class Looper {
private static void prepare(boolean quitAllowed) {
//如果该线程存在looper 直接抛异常
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//将looper 通过 threadLocal 赋给 当前线程
sThreadLocal.set(new Looper(quitAllowed));
}
}
public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
}
public class ThreadLocal<T> {
// 此时的 T->Looper
public T get() {
//获取当前线程的 threadLocal
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
//线程中维持着一个 ThreadLocal.ThreadLocalMap 类型的 threadLocals 变量
//该map 是一个 Entry(ThreadLocal<?> k, Object v) 类型对象
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
//获取 该线程 looper
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
}
1.线程中只能持有一个looper
2.public static void loop() 无限循环 获取 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.");
}
//获取looper中持有的 MessageQueue
final MessageQueue queue = me.mQueue;
//开启无限循环
for (;;) {
// messageQueue 获取 msg
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
try {
//msg.target=>handler
//handler.dispatchMessage() =>方式msg的 handler 处理message
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//msg 消耗完直接回收,加到闲置message链表表头,前面已讲
msg.recycleUnchecked();
}
}
3.public static void prepareMainLooper()
主线程中创建 的looper
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
4.Handler (快递员)
Handler 使我们平常使用最多的,常用使用方法
1.Handler handler =new Handler()
2.handler.sendMessenge()....
3..handler.post(Runnable b)...
4.dispatchMessage /handleMessage
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()");
}
//消息 messagequeue
mQueue = mLooper.mQueue;
//handler callback
mCallback = callback;
//是否为异步handler
mAsynchronous = async;
}
new Handler()
1.将handler 和 looper 关联起来,所以,在使用handler的前,必须要新建 looper
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
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);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
handler .post() ---->handler.sendMessage()-------->sendMessageAtTime-->MessageQueue.enqueueMessage(queue, msg, uptimeMillis) :是不是似曾相识,哈哈,没错,回到了我们前面讲的,MessageQueue 中(忘记了,可以看下前面)。
//looper.looper() 方法中,获取了message中的handler ,并调用dispatchMessage() 方法
public class Handler {
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
// handler.post(callback)
handleCallback(msg);
} else {
if (mCallback != null) {
// new Handler(mCallback)
if (mCallback.handleMessage(msg)) {
return;
}
}
//最后调用handler中的 handleMessage 方法
handleMessage(msg);
}
}
}
public final class Looper {
public static void loop() {
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);
}
}
handler 发送message 后, 必须通过looper.loop() 才能让发动机动起来,传送带开始传送事件 !