美文网首页深入浅出Android待读大牛聚集之地
Android 深入理解Handler, Looper, Mes

Android 深入理解Handler, Looper, Mes

作者: 伪文艺大叔 | 来源:发表于2017-01-25 13:14 被阅读368次

    Handler, Looper, Message三者之间的关系基本上是面试官必问问题之一,那今天让我们从源码的角度来解读一下它们之间的关系

    Handler 构造
    //主线程创建Handler 
    Handler handler = new Handler();
    
    public Handler() {
        this(null, false);
    }
    
    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;
     }
    

    以上就是Handler的构造方法,下面我们来分析下两个重点

      mLooper = Looper.myLooper();
    
      public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
      }
    

    通过myLooper方法得到一个Looper,sThreadLocal存放的Looper,是主线程main方法中创建的

      mQueue = mLooper.mQueue;
    

    mQueue 为消息队列,是从Looper中获取,接下来看它发送消息的逻辑

    Handler 发送消息
     handler.sendMessage(new Message());
    
      public final boolean sendMessage(Message msg)
        {
            return sendMessageDelayed(msg, 0);
        }
    
     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);
      }
    
     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
      }
    

    上面代码经过层层调用,最终把消息插入到MessageQueue 队列中(queue队列就是在构造方法中从Looper得到的 )

    //把Hander对象赋值给消息的target 的属性
     msg.target = this;
    

    从构造方法和发送消息可以得出:首先得到主线程创建的Looper对象,然后得到Looper对象中的MessageQueue,然后发送消息到MessageQueue队列当中,插入消息队列以后要如何处理呢?我们来看看Looper的一些方法

    Looper prepare方法

    主线程在创建的时候会调用Looper的prepare和loop方法,那prepare方法里面干了什么呢?

    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对象然后存放到sThreadLocal中,而Handler对象中的Looper就是从sThreadLocal中获取的,接下来看看loop方法

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

    首先得到looper里的消息队列,然后循环从消息队列里取message,最后调用message里target的dispatchMessage方法,target就是发送消息的Handler对象

     public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
      }
    

    主要看handleMessage方法这行代码,handleMessage需要我们自己去实现,下面这行代码什么时候会调用呢?

     if (msg.callback != null) {
           handleCallback(msg);
      }
    

    这段代码是什么意思呢?这里涉及到发送消息的另外一种方式,我们有时候为了简单会这样调用

     handler.post(new Runnable() {
         @Override
         public void run() {
    
         }
      })
    
     //调用的post方法
     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;
     }
    

    从getPostMessage方法中可以看到,首先从消息池中得到消息对象,然后把我们创建的Runnable对象赋值给消息的callback属性,我们回过头看看上面的判断代码,判断callback是否为空,不为空调用handleCallback方法

    private static void handleCallback(Message message) {
            message.callback.run();
    }
    

    方法里面就是回调callback的run方法,run方法就是我们自己的业务逻辑代码

    总结

    到此三者之间的关系已经分析完毕,主线程在创建时创建Looper对象,在Looper构造方法中创建消息队列MessageQueue,调用Looper的loop方法启动消息循环;然后Handler在创建时从sThreadLocal中取主线程Looper对象中MessageQueue,发送消息插入到消息队列,loop循环取出消息,调用Handler的handleMessage方法或callback回调方法完成消息处理,所以Handler对象必须关联一个Looper对象,在子线程中使用Handler必须要调用Looper的prepare和loop方法,因为它需要Looper的消息队列和消息循环处理,而主线程在创建时已经创建了Looper对象,并启动了Looper循环,所以在主线程中使用Handler不需要调用这2个方法。

    相关文章

      网友评论

      本文标题:Android 深入理解Handler, Looper, Mes

      本文链接:https://www.haomeiwen.com/subject/yfutittx.html