Android消息机制Hnadler

Handler、Looper、MessageQueue作用与分工

  • Handler:负责发送消息(sendMessage(Message) 或post(Runnale))并处理接受到消息
  • Looper:负责轮询消息队列(MessageQueue)并取出消息回传给Hanlder
  • MessageQueue:负责消息的存储,主要操作有消息的插入(enqueueMessage())与读取next()。
    这里写图片描述

接下来分析从Hnadler初始化到处理消息handleMessage中整个过程是怎么回事

一. 创建Handler,Handler mHandler=new Handler(),做了哪些操作???

这里写图片描述

  • 能得到两个重要信息点,一个通过Looper.myLooper()获取当前线程的Looper对象,另外一个就是获取MessageQueue对象;起初你可能会有疑问,Looper和MessageQueue是什么时候创建的,接下来看源码:
    这里写图片描述
    这里写图片描述
  • ThreadLocal(类似HashMap,根据key取value)根据当前线程,取出同一线程对应的Looper对象。在获取Looper对象之前可能sThreadLocal没有Looper存储值是一个空对象,要先调用Looper.prepare()对它进行初始化。ThreadLocal其实是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取存储的数据,对于其他线程则无法获取到数据,可以从ThreadLocal源码看出,提供了set和get方法。
    这里写图片描述
    这里写图片描述
    上面提到了在sThreadLocal.get()获取Looper对象之前,必须先调用Looper.prepare()对它进行初始化,否则抛出Can’t create handler inside thread that has not called Looper.prepare()异常,如下:
 private class DownloadThread extends Thread{
        @Override
        public void run() {
            super.run();
             //Looper.prepare();
            Handler handler = new Handler();
            handler.sendMessage(Message.obtain());
        }
    }

这里写图片描述

接下Looper.prepare()看看做了哪些操作!!!
这里写图片描述
这里写图片描述

  • 从源码可以看出,在Looper的构造方法中它会创建一个MessageQueue即消息队列,然后将当前线程的对象保存起来。

接下来只剩Looper.prepare()这个何时调用了,是个疑问??都说Handler的使用必须调用此函数,在我们开发中并没有使用该函数,,其实在我们应用程序一启动入口时,系统默认创建了主线程,与此同时,在程序入口就已经帮我们初始化了Looper对象,我们可以ActivityThread这个类中发现

这里写图片描述
这里写图片描述
Looper最重要的一个方法就是loop,相当于MessageQueue中一把钥匙,只有调用了该方法,才能打开MessageQueue这把锁,消息循环系统才会起相应的作用,源码:


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
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            final long end;
            try {
            //msg.target是发送消息的对象Handler,由此可知Handler发送消息的任务在此交给了dispatchMessage来处理分发到主线程。
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (slowDispatchThresholdMs > 0) {
                final long time = end - start;
                if (time > slowDispatchThresholdMs) {
                    Slog.w(TAG, "Dispatch took " + time + "ms on "
                            + Thread.currentThread().getName() + ", h=" +
                            msg.target + " cb=" + msg.callback + " msg=" + msg.what);
                }
            }

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

接下来看看Handler的sendMessage方法,就是把Message对象插入消息队列中

public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
//将消息对象Message,插入消息队列中
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);
    }

经过上面的分析,基本知道Handler、Looper、MessageQueue这三者关系

在创建Handler之前,必须初始化Looper对象(Looper.prepare)并保存当前线程,一个线程对应一个Looper对象;接下来Handler通过sendMessage方法发送消息,会向MessageQueue消息队列插入一条消息,然后Looper调用loop方法遍历是否有新消息,当接受到新消息时,会交由Handler对象处理,Handler会调用dispatchMessage方法将消息分发出去到主线程,最后调用Handler的handleMessage方法处理消息。

猜你喜欢

转载自blog.csdn.net/hzw2017/article/details/79474945