Android应用程序消息处理机制三部分:消息循环,消息发送,消息处理
Looper:消息循环
当我们打开一个应用程序的时候,系统会默认帮我们创建一个主线程ActivityThread(这是一个受保护的类,可以直接打开sdk位置,找到该类),在main方法中已经帮我们实现Looper。所以我们不需要再次实现该方法,也可以实现消息的发送,处理。当我们创建一个线程时就需要实现Looper来实现消息的循环处理。
下面看一下Looper的创建过程:
public static void prepare() {
//初始化
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//通过该行代码表明:一个Thread只能有一个Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
通过以上可以看出调用Looper的prepare方法,会默认帮我创建一个Looper,值得注意的是该方法表明一个Thread智能有一个Looper。存储到ThreadLocal中。对于ThreadLocal这里不做讲解,有兴趣的可以自行去看。如果看过源码的话会发现Looper中还有一个方法 prepareMainLooper()
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
该方法就是我们之前所说的ActivityThread创建默认Looper时所调用,Looper还为我们提供了getMainLooper方法用于在任何地方获取主线程Looper对象。
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
接下来就是Looper中的消息循环方法loop,该方法是一个死循环,我们可以下看下源码:
//调用loop进入到消息循环
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.");
}
//获取当前消息队列
final MessageQueue queue = me.mQueue;
//循环取出下一消息,调用diapatchMessage分发,直到target=null
for (;;) {
//next方法用于判断,线程是否进入等待状态:1没消息,2延迟,定时发送的消息。消息队列中消息按照时间顺序排列
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
try {
//分发消息
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
}
}
这里只贴出部分需要的源码,透过源码看一看出,loop中通过消息队列的next方法循环取出消息,若有新消息,则调用msg.target.dispatchMessage(msg);进行分发处理,这里msg.target目标对象就是发送消息的Handler对象。若无消息则next进入阻塞,刚才说过loop是个死循环除非next方法为空,才会跳出循环。
Looper提供了quit和quitSafely方法退出Looper。不同之处在于quit直接退出Looper,quitSafely设置一个安全退出标记,待消息队列中已有消除处理完毕,才会退出Looper,此时next方法返回null。需要注意的时loop方法要放在最后执行,因为loop方法之后的内容不会立即执行,有兴趣的可以试一下。
Handler:消息发送,消息处理
Handler包含消息的发送和处理两种过程。
消息发送
Handler 可以通过Post和send方法进行发送消息,其中post内部也是通过send发送消息:
public final boolean sendMessage(Message msg)
public final boolean sendEmptyMessage(int what)
public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
像MessageQueue中插入一消息通过enqueueMessage方法,MessageQueue的next方法就会返回一条信息给Looper对象,最终还是调用handler 的dispatchMessage方法。
消息处理
在这里就需要看一下上面所说的dispatchMessage方法,我们看一下源码:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Handler处理消息过程:先查看Message的Callback 方法是否为空,不为空则调用handleCallback方法直接处理消息,可以看出调用了Message内部进行处理。
private static void handleCallback(Message message) {
message.callback.run();
}
Message的Callback 方法为空,那么就继续判断mCallback 是否为空 ,这里的mCallback 是Handler 中的一个接口:
public interface Callback {
public boolean handleMessage(Message msg);
}
通过Callback 可以使用该方式创建一个Handler对象,就是可以创建出Handler实例但并不需要派生出Handler的子类,
public Handler(Callback callback) {
this(callback, false);
}
继续讲解消息的处理,若mCallback不为空,则调用接口中的handleMessage方法直接处理,若返回false,则最终调用handleMessage处理。
再添加一点:一个Thread对应一个Looper,一个Looper对应一个消息队列。
结束语:这是我对Android中消息机制的一点理解。