Android 深入理解Handler, Looper, Message 三者之间的关系

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个方法。

    原文作者:伪文艺大叔
    原文地址: https://www.jianshu.com/p/f2150400db9a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞