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

来源:互联网 发布:cydia软件源福利 编辑:程序博客网 时间:2024/05/17 04:15

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

0 0
原创粉丝点击