Android异步消息处理机制:在Android中,只有主线程才能操作UI,但是主线程不能进行耗时操作,否则会阻塞线程,引起ANR异常。如果在子线程中要更新UI,一般是通过Handler发送消息,主线程接收消息并进行相应的逻辑处理,异步消息处理线程启动后,会进入一个无限的循环体中,每一次循环,从消息队列中取出一个消息,然后调用相应的消息处理函数,执行完成一个消息后则继续循环,若消息队列为空,线程则会阻塞等待; 异步消息处理机制主要有三部分组成:
一. Looper:系统提供了prepare(), loop()两个方法,
首先看一下Looper的构造方法,在对Looper实例化时,内部创建了一个MessageQueue 消息队列
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
prepare()方法,源码所示:
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));
}
由源码可以看出,在执行prepare方法时,首先会从ThreadLoad中获取Looper实例,判断当前线程的Looper实例是否为空,不为空则抛出异常;这也就能说明prepare方法只能执行一次,一个线程中只能存在一个Looper实例;
loop() 方法,源码所示:
public static void loop() {
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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
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);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
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();
}
}
public static Looper myLooper() {
return sThreadLocal.get();
}
由源码可以看出,执行loop 方法时,首先会执行 myLooper 方法获取一个Looper实例,如果Looper实例为空时,则抛出异常,这同时也说明:loop方法必须在prepare方法后执行; 再获取MessageQueue消息队列实例,然后进入到无限循环的循环体中,消息队列取出一个消息,然后调用 msg.target.dispatchMessage(msg)交给msg的target的dispatchMessage(msg)方法去处理消息,其实msg的target也就是Handler对象;
Looper的主要作用:1.与当前线程绑定,保证一个线程只有一个Looper实例,同时也确保只有一个MessageQueue
2.loop() 方法,不断从消息队列中取出消息,交由msg.target.dispatchMessage(msg)(Handler)处理
二.Handler:消息的发送及处理
首先看一下构造方法
public Handler() {
this(null, false);
}
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());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
由构造方法可以看出,实例化Handler时,同时也会通过Looper.myLooper()方法获取该线程中的唯一Looper实例,再获取到MessageQueue消息队列,由此就可以看出Handler, Looper, Message 三个联系在了一起;
Handler 发送消息:
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postDelayed(Runnable r, long delayMillis){
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r; //Message的成员变量callback其实就是一个Runnable
return m;
}
由此可以看出:无论Handler实例以sendMessage(Message msg)或post(Runnable r)的方式去发送消息,最终都是执行 enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)该方法(此时在UI线程中运行了),在该方法中首先通过msg.target = this将Handler实例赋值给了Message的成员变量target(实际上也是个Handler实例),通过MessageQueue消息队列实例调用enqueueMessage(msg, uptimeMillis)方法,将Message实例保存到消息队列中去;
前面说到:Looper执行loop方法时,会从消息队列中获取到消息,当没有消息时则会进入到阻塞状态,当获取到消息时,消息对象会调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);
}
}
public void handleMessage(Message msg) {
}
private static void handleCallback(Message message) {
message.callback.run();
}
如果msg.callback != null时,也就是Runnable不为空,则会执行callback回调,也就是我们的Runnable对象;如果为空时则会调用handleMessage方法,但是我们看到该方法是一个空方法,实际上如果消息的类型不是Runnable类型,则消息的回调是由我们进行控制,我们一般都会进行该方法的复写,然后根据msg.what进行消息处理,例如:
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case value:
break;
default:
break;
}
}
};
流程总结:
1、首先Looper.prepare()会在本线程保存一个Looper实例,然后在Looper实例中保存一个MessageQueue实例,因为Looper.prepare()方法只能调用一次,所以一个线程中只能有一个Looper实例,保存在ThreadLoad中,同理MessageQueue实例也只有一个;
2、Looper.loop()会让当前线程进入一个无限循环,不断从MessageQueue中获读取消息,然后调用msg.target.dispatchMessage(msg)方法执行;
3、Handler的构造方法,首先会获取当前线程中的Looper实例,进而与Looper中的MessageQueue实例相关联;
4、Handler的sendMessage(msg)/post(runnable)方法会将Handler自身赋值给msg.target,然后进入到消息队列中
5、创建Handler实例时,如果是以sendMessage(msg)方式发送消息,我们会复写handleMessage(msg)方法,自己进行消息的处理;如果是以post(runnable)方法发送消息,则系统会自动进行消息的回调,然后进行处理