概述
Android异步事件处理有很多方式,常用的有Handler的send(message)系列方法,post(runnable)系列方法,view.post(runnable)方法,runOnUiThread方法,AsyncTask以及EventBus。前面几种都是基于Handler机制,AsyncTask基于handler和线程池的封装,EventBus是基于发布者和订阅者的库,主要可以代替handler,intent,broadcastReceiver在Fragment,Activity,Service,线程之间传递消息,优点是开销小,代码更优雅,最重要的是将发送者和接收者解耦。
我们主要来看下Handler机制。
Handler机制
提到Handler就会涉及到MessageQueue和Looper。
Messagequeue并不是队列,而是单链表(便于插入和删除),就和ActivityThread,ApplicationThread和ThreadLocal不是线程一样(前者是UI线程的一个类,中间的实际上是一个binder,后面的是为了在不同的线程中保存数据副本)。Looper是每个MessageQueue的管家(ThreadLocal类型,每个线程都有自己的looper),它会无限循环的查找是否有新消息,没有就一直阻塞在那里,有就取出来交给handler处理。
MessageQueue 主要有两个方法enqueueMessage()和next()
boolean enqueueMessage(Message msg, long when) {
...}
Message next() {
...}
enqueueMessage方法主要是单链表的插入操作,next方法是一个无限循环的方法,有就反回该Message并移除,没有就阻塞在那里。
每个线程要异步通信都只能有一个looper,没有looper就会报错
public static void prepare() {
prepare(true);
}
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));
}
有looper在创建会抛出异常,prepare()即为当前线程创造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();
}
}
/**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
prepareMainLooper()会在ActivityThread的main方法中被调用,
主要是为UI线程创建Looper(getMainLooper方法可以在任何地方获取主线成的Looper),除此之外还会创建activitythread实例,并开启消息循环.
public static void main(String[] args) {
...............
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
Looper还提供了退出方法,quit()和quitSafely();前者会让looper直接退出,后者会设定一个退出标记,等消息队列的所有消息处理完后再推出,类似于intentservice退出。
接着我们看消息循环方法:
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();
}
}
loop()方法是一个死循环,只有当消息队列设定退出标记时它的next方法返回null时,这个时候会跳出循环。looper取出消息后把message分发给对应的handler,在相应的线程中处理事件。
接着我们来看Handler类,Looper类从MessageQueue中取出message交给hanlder来处理,在loop()中调用handler的dispatchMwssage方法;
msg.target.dispatchMessage(msg);
msg.target即为对应的handler;我们来看看handler的dispatchMessage方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
同时handler的post系列(runnable)方法也是通过send系列(message)方法实现的,把runnable对象包装成message对象,最终还是会调用handler的dispatchMessage方法
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
当message的callback(runnable)不为null时在对应handler所在线程执行runnable的run()。
private static void handleCallback(Message message) {
message.callback.run();
}
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
并且我们可以通过new Handler(callback)来创建handler对象(当我们不想通过handler的匿名内部类并重写handlerMessage方法时,可以通过callback接口来实现),当message的callback为null时,会判断handler对应的callback是否为null,不为null执行callback的handleMessage方法,否则执行handler的handleMessage方法。
view的post方法
该系列也是调用handler的post系列方法来完成
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
runOnUiThread()
当前线程为主线成,执行runnable的run(),否则调用handler的post系列方法
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}