Looper,Handler,MessageQueue,Message之间的关系

Android异步消息机制架构:

Android异步消息处理架构,其实没那么复杂。简单来说就是looper对象拥有messagequeue,并且负责从messagequeue中取出消息给handler来处理。同时handler又负责发送messagelooper,由loopermessage添加到messagequeue尾部。就一个圈儿。下面给出图解:

所以很明显handlerlooper是来联系在一起的。需要说明的是,多个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对应的handlerlooper对象管理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()方法会自动的设置Messagetarget为当前的Handler。得到Message之后可以调用sendToTarget(),发送消息给HandlerHandler再把消息放到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<? 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;
}

/**
 * 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对象,以及loopermessagequeue
    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)方法里面的代码了吧。

猜你喜欢

转载自my.oschina.net/u/2987490/blog/1457253
今日推荐