zoukankan      html  css  js  c++  java
  • 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()使用方式的一种变体。

  • 相关阅读:
    CMS前世今生
    叫练手把手教你读JVM之GC信息
    原来我还有网络天赋
    最简单的JVM内存结构图
    图解CyclicBarrier运动员接力赛
    图解定时任务线程池
    并发队列:ArrayBlockingQueue实际运用场景和原理
    ReentrantReadWriteLock读写锁简单原理案例证明
    JavaScript中的Function类型浅析
    JS数组整理
  • 原文地址:https://www.cnblogs.com/luction/p/3637663.html
Copyright © 2011-2022 走看看