Looper用于运行一个线程的消息循环。 默认情况下线程不开启Looper; 线程中要创建Looper,参照下面代码:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
由此可知,loop()是执行循环机制的主要方法,下面看loop()到底做了什么事情。
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
...
msg.recycleUnchecked();
}
}
首先获取Looper的消息队列,开启循环,不断地从消息队列中取出Message,把Message分发给目标Handler(msg.target),target实在Handler发送消息时设置的参数。消息交给Handler处理之后,回收Message。整个过程发生在ActivityThread线程中,就是主线程。
Handler在处理消息时,做了什么事情
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
如果客户端在Message中设置的回调对象(Runable),执行回调 反之,执行Handler的全局回调,mCallback通过构造函数传入,最后调用handleMessage方法,处理消息。
至此,以上是Looper循环做的所有事情,Looper机制的特点是
1.消息在Looper创建的线程中执行handleMessage
2.Handler与Looper必须在同一个线程中,他们是1对多的关系
3.Handler提供了IMessenger.Stub实现,IMessager是Binder的封装,负责进程间通讯,Hander负责具体的逻辑处理 。所以,不同的进程或线程可以获取IMessager,然后挂进程发送消息
4.串行化执行
额外要说明的是Message的创建和回收,Message实现了单向链表结构,它的访问逻辑是LIFO(后进先出),
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,将链表头部后移,Message的next置空。把消息池的大小减一 反之,创建新的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) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
从上可以看出,Message回收,就是把参数初始化,然后把空的Message插入到链表的头部
同步锁的作用域是整个应用,在虚拟机内部是有效的。 消息池的使用避免了大量的内存创建和销毁。