Android Handler源码分析

2018-12-14  本文已影响6人  孤独的根号十二

首先,我们应该知道,整个应用的入口函数是ActivityThread的main函数,UI线程的消息循环也是在这个方法中创建的:


 public static void main(String[] args) {
  .......省略之前代码
 
   Looper.prepareMainLooper();

     ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
      Looper.loop();
}

主要只有三句主要代码
咱们一句一句分析,首先prepareMainLooper

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

里面调用了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));
    }

这里的sThreadLocal是一个ThreadLcoal对象,他可以将当前Looper和当前线程即主线程进行绑定,它是一个保证线程安全的类,不了解的小伙伴可以自行了解一下,值得一提的Looper的构造方法中初始化了一个MessageQueue,并传入了一个false

myLooper方法就是从刚才的sThreadLocal得到一个Looper对象,并且赋值给自己的一个static对象

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

至此prepareMainLooper方法分析完成,回到main函数,后面只是生成一个handler对象,此处不作分析,重点分析下一句 Looper.loop();

   public static void loop() {
  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();
        }

}

里面开启了一个for循环,有一个queue.next();方法,就是不断的从队列中取得消息,当然它并不是按照顺序取得,还记得 postDelayed方法吗,我们可以传一个延迟时间进去,所以,取的时候会判断是否到达那个时间,没到那个时间,则会将其在链表的位置中往后放,直到到那个时间,才能取到,看下面这一句

    msg.target.dispatchMessage(msg);

这个 msg.target是什么,其实他就是发送这个msg的handler对象,追中Handler的sendMessage方法,最终会调用enqueueMessage方法

    private boolean enqueueMessage(android.os.MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;// 这里将自己赋值给message
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

回到Looper里面 msg.target.dispatchMessage(msg)会调用handler的dispatchMessage;

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

最终会调用handleMessage

上一篇下一篇

猜你喜欢

热点阅读