Handler Looper源码解析(Android消息传递机制)

Android的Handler类应该是常用到的,多用于线程间的通信,以及子线程发送消息通知UI线程刷新View等等。这里我主要总结下我对整个消息传递机制,包括Handler,Looper,Message,MessageQueue类的理解。

 

Looper类:每一个线程都只能拥有一个Looper对象,这里Android是通过将Looper对象设置为当前线程的线程局部变量(这里涉及到ThreadLocal类),可以通过调用Looper.prepare()方法来使当前线程拥有一个Looper对象(主线程不用调用,因为主线程本身已经是拥有Looper对象了)。这里贴出prepare()的源码

 

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");  /*如果当前线程已经拥有Looper对象,就会报错。*/

        }

        sThreadLocal.set(new Looper(quitAllowed));/*新建Looper对象并设置为当前线程的线程局部变量。*/

    }

 而Looper类的主要作用是进行消息循环,Looper类维护了一个MesageQueue,通过不停调用loop()方法来取出MeesageQueue中的Message并进行相应的处理。

public static void loop() {

        final Looper me = myLooper();  /*得到当前线程的Looper对象*/

        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.recycle();/* 回收msg(重复利用Message对象) */

        }

    }

这个留意到loop()方法里对Message的处理方式是调用msg.target.dispatchMessage(msg);,关于这个方法,我们了解完Handler后再看。

 

MeesageQueue:Message队列,队列就不详解了,先进先出。

Handler:Handler的作用主要是分发信息 相关方法有:

        post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)

 public final boolean sendMessage(Message msg)

    {

        return sendMessageDelayed(msg, 0);

    }





  public final boolean sendEmptyMessage(int what)

    {

        return sendEmptyMessageDelayed(what, 0);

    }



 public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {

        Message msg = Message.obtain();

        msg.what = what;

        return sendMessageDelayed(msg, delayMillis);

    }





 public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {

        Message msg = Message.obtain();

        msg.what = what;

        return sendMessageAtTime(msg, uptimeMillis);

    }



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);

    }

 发现这些方法最后都是调用enqueueMessage(),看看这个方法的源码

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

        msg.target = this;

        if (mAsynchronous) {

            msg.setAsynchronous(true);

        }

        return queue.enqueueMessage(msg, uptimeMillis);

    }

 调用了MessageQueue的enqueueMessage方法,将Message对象加入了队列中去

 

再看看这几个方法

public final boolean post(Runnable r)

    {

       return  sendMessageDelayed(getPostMessage(r), 0);

    }



 public final boolean postAtTime(Runnable r, long uptimeMillis)

    {

        return sendMessageAtTime(getPostMessage(r), uptimeMillis);

    }



public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)

    {

        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);

    }



public final boolean postDelayed(Runnable r, long delayMillis)

    {

        return sendMessageDelayed(getPostMessage(r), delayMillis);

    }

 发现post()系列的方法最后都是调用sendMessage系列的方法只是传入的Message对象有所不同,我们再看看getPostMessage()

  private static Message getPostMessage(Runnable r) {

        Message m = Message.obtain();

        m.callback = r;

        return m;

    }



    private static Message getPostMessage(Runnable r, Object token) {

        Message m = Message.obtain();

        m.obj = token;

        m.callback = r;

        return m;

    }

 发现其实就是把Runnable对象赋给Message的callback。通过以上代码的分析,基本上对整个消息机制有个概念了,当我们调用Handler的sendMessage()或post()等一系列方法时,Handler会将消息加入到MessageQueue中,这个MessageQueue为Handler对应的Looper对象所维护的queue(创建Handler时可以传入Looper对象,无参情况下为当前线程的Looper,想具体了解可以看下Handler的构造函数,这里不再赘述)然后由Looper类的loop()方法将消息取出。并做处理。至于怎么处理,我们就要看下msg.target.dispatchMessage(msg)这个方法了。我们知道msg的target是一个Handler对象,看下这个方法的源码

 

public void dispatchMessage(Message msg) {

/* 如果callback不为空,即发送消息的时候传入了Runnable对象,也就是调用的是post()系列的方法。那么就会执行handleCallback()这个方法,否则执行handleMessage() */

        if (msg.callback != null) {

            handleCallback(msg);

        } else {

            if (mCallback != null) {

                if (mCallback.handleMessage(msg)) {

                    return;

                }

            }

            handleMessage(msg);

        }

    }

 handleMessge()方法想必大家都很熟悉,这个方法是我们new一个Handler对象时常常会去重写的,然后处理消息时会回调这个方法。再看看handleCallback()

private static void handleCallback(Message message) {

        message.callback.run();

    }

 代码很简单,就是调用了callback的run()方法。这里要特别注意的是调用的是run()而不是start(),这意味着将不会另起一个线程。而是在Looper对象所在的线程执行。至于为什么这么做笔者认为由于这样做即使是多次post也不需要开启多个线程,大大提高了程序的性能,同时,在某些情况下,我们希望能够顺序执行callback,那么使用这个方法无疑是非常棒的。当然,如果是要并发执行作那么就得使用其他法子了。总的来说post()方法相当于sendMessage()+handleMessage()使用方式的一种变体。

你可能感兴趣的:(android)