Android异步消息机制架构:
Android异步消息处理架构,其实没那么复杂。简单来说就是looper
对象拥有messagequeue
,并且负责从messagequeue
中取出消息给handler
来处理。同时handler
又负责发送message
给looper
,由looper
把message
添加到messagequeue
尾部。就一个圈儿。下面给出图解:
所以很明显handler
和looper
是来联系在一起的。需要说明的是,多个message
可以指向同一个handler
,多个handler
也可以指向同一个looper
。还有一点很重要,普通的线程是没有looper
的,如果需要looper
对象,那么必须要先调用Looper.prepare()
方法,而且一个线程只能有一个looper
。调用完以后,此线程就成为了所谓的LooperThread
,若在当前LooperThread
中创建Handler
对象,那么此Handler
会自动关联到当前线程的looper
对象,也就是拥有looper
的引用。
Looper
Looper
就是一个管理messagequeue
的类。下面是这个类的源码。
public class Looper { ...... private static final ThreadLocal sThreadLocal = new ThreadLocal(); final MessageQueue mQueue;//拥有的消息队列 ...... /** * Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ //创建新的looper对象,并设置到当前线程中 public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } ····· /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ //获取当前线程的looper对象 public static final Looper myLooper() { return (Looper) sThreadLocal.get(); } private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); } ......}
调用完Looper.prepare()
之后,在当前的线程创建的Handler
才能拥有当前线程的looper
。然后调用loop()
来开启循环,处理message
。下面是Looper类下的loop方法部分源码:
public static void loop() { final Looper me = myLooper();//获取looper对象 if (me == null) { //若为空则说明当前线程不是LooperThread,抛出异常 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } 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 //打印log,说明开始处理message。msg.target就是Handler对象 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } //重点!!!开始处理message,msg.target就是Handler对象 msg.target.dispatchMessage(msg);//dispatchMessage:发送消息 //打印log,处理message结束 if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } ..... }}
是一个大的循环,不断从消息队列出取出消息。然后调用一个很关键的方法msg.target.dispatchMessage(msg)
开始处理消息。msg.target
就是message
对应的handler
。looper
对象管理MessageQueue
,从中取出message
分配给对应的handler
来处理。
Message
Message
就是一些需要处理的事件,比如访问网络、下载图片、更新ui界面什么的。Message
拥有几个比较重要的属性。
public int what 标识符,用来识别message
public int arg1,arg2 可以用来传递一些轻量型数据如int之类的
public Object obj Message
自带的Object类字段,用来传递对象
Handler target 指代此message
对象对应的Handler
如果携带比价复杂性的数据,建议用Bundle
封装,值得注意的地方是,虽然Message
的构造方法是公有的,但是不建议使用。最好的方法是使用Message.obtain()
或者Handler.obtainMessage()
能更好的利用循环池中的对象。一般不用手动设置target
,调用Handler.obtainMessage()
方法会自动的设置Message
的target
为当前的Handler
。得到Message
之后可以调用sendToTarget()
,发送消息给Handler
,Handler
再把消息放到messagequeue
的尾部。这个方法的源码如下:
/** * Sends this Message to the Handler specified by {@link #getTarget}. * Throws a null pointer exception if this field has not been set. */public void sendToTarget() { target.sendMessage(this);//此处的target是message对应的Handler.}
Handler
它的构造函数如下:
/** * Default constructor associates this handler with the {@link Looper} for the * current thread. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. */public Handler() { this(null, false);}/** * Constructor associates this handler with the {@link Looper} for the * current thread and takes a callback interface in which you can handle * messages. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. * * @param callback The callback interface in which to handle messages, or null. */public Handler(Callback callback) { this(callback, false);}/** * Use the provided {@link Looper} instead of the default one. * * @param looper The looper, must not be null. */public Handler(Looper looper) { this(looper, null, false);}/** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. */public Handler(Looper looper, Callback callback) { this(looper, callback, false);}/** * Use the {@link Looper} for the current thread * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */public Handler(boolean async) { this(null, async);}/** * Use the {@link Looper} for the current thread with the specified callback interface * and set whether the handler should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class 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;}/** * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. Also set whether the handler * should be asynchronous. * * Handlers are synchronous by default unless this constructor is used to make * one that is strictly asynchronous. * * Asynchronous messages represent interrupts or events that do not require global ordering * with respect to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param looper The looper, must not be null. * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * * @hide */public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; //由此可知,它拥有looper对象,以及looper的messagequeue mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}
要通过Handler
来处理事件,可以重写handleMessage(Message msg)
,也可以直接通过post(Runnable r)
来处理。这两个方法都会在looper循环中被调用。
loop循环中处理信息的msg.target.dispatchMessage(msg)
方法源码:
public void dispatchMessage(Message msg) { //注意!这里先判断message的callback是否为空,否则就直接处理message的回调函数 if (msg.callback!= null) { //这里的callback就是上面的Runnable handleCallback(msg); } else { if (mCallback != null) { //正是在这调用我们平常重写handleMessage if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
首先判断是否用的是handler的post方法,如果是就执行r里面run()方法的代码,否则就判断handler的构造函数是否初始化了CallBack,是的话就会执行这个接口里面handleMessage(msg)方法,;如果放回的是false,最后就会调用handleMessage(msg)(建立handler时重写的方法,如果没有重写,就什么都不会执行)。下面是handler的post方法的源码:
/** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0);//发送消息}
上面源码中getPostMessage(r)方法的源码:
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; //就是上面的msg.callback,如果调用了handler的post方法,它就会不为空。 return m;}
上面的 if (msg.callback!= null) { //这里的callback就是上面的Runnable handleCallback(msg); }的handleCallback(msg)源码:(就是运行run方法里面的代码)
private static void handleCallback(Message message) { message.callback.run();}
而 if (mCallback.handleMessage(msg)) { return; }中的handleMessage(msg)源码如下:
/** * 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);}
所以现在知道loop循环中处理信息的msg.target.dispatchMessage(msg)
方法里面的代码了吧。