美文网首页
Android Handler源码分析

Android Handler源码分析

作者: 孤独的根号十二 | 来源:发表于2018-12-14 16:55 被阅读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

    相关文章

      网友评论

          本文标题:Android Handler源码分析

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