美文网首页
Handler源码分析

Handler源码分析

作者: 空老表 | 来源:发表于2018-09-10 14:49 被阅读0次

前言:本来打算先写android启动流程分析的,但是在里面看到Looper.loop(),就看了一遍Handler的源码,之前比较晦涩的地方,现在一下就看明白,因此就想记录一下,方便以后查阅。

众所周知,我们在子线程更新UI之前需要切换到主线程(因为View绘制之前会检查线程),常规操作如下

           thread {                                    
                    //切换线程
                    _handler.obtainMessage().sendToTarget()
                }.start()
                      
        
           private val _handler = @SuppressLint("HandlerLeak")
            object : Handler() {
                override fun handleMessage(msg: Message?) {
                    super.handleMessage(msg)
        
                }
            }

非常规操作:

  thread {                   
                Looper.prepare()
                //ui operate
                Looper.loop()
                
            }.start()

其实道理都是一样的,都是先创建一个Looper对象,然后在Looper对象里面进行操作,所以,今天主要分析要落在Looper.loop()身上了
Handler构造

               fun Handler(callback: Callback?, async: Boolean): ??? {
                        if (FIND_POTENTIAL_LEAKS) {
                            val klass = javaClass
                            if ((klass.isAnonymousClass || klass.isMemberClass || klass.isLocalClass) && klass.modifiers and Modifier.STATIC == 0) {
                                Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.canonicalName)
                            }
                        }
                        //这里创建Looper对象
                        mLooper = Looper.myLooper()
                        if (mLooper == null) {
                            throw RuntimeException(
                                    "Can't create handler inside thread that has not called Looper.prepare()")
                        }
                        mQueue = mLooper.mQueue
                        mCallback = callback
                        mAsynchronous = async
                    }

Looper.prepare()

        private fun prepare(quitAllowed: Boolean) {
            if (sThreadLocal.get() != null) {
                throw RuntimeException("Only one Looper may be created per thread")
            }
            sThreadLocal.set(Looper(quitAllowed))
        }

loop()主要代码如下

        fun loop() {
            //me = sThreadLocal.get(),可以看到是从prepare里面去取初始化的Looper
            val me = myLooper()
                    ?: throw RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.")
        //获取消息队列,所有的msg循环都是在消息队列里面完成的,通过msg.next进行传递
            val queue = me!!.mQueue  

            while (true) {
            //取一条消息
                val msg = queue.next()
                        ?: 
                        return         

                val slowDispatchThresholdMs = me!!.mSlowDispatchThresholdMs      
                //这句代码是不是很熟悉了,我们在新建handler的时候,重写的最多的代码就是这一句了
              //target其实就是一个msg内部的Handler
                msg.target.dispatchMessage(msg)
                
                msg.recycleUnchecked()
            }
        }

while里面是个无限循环,主要代码还是在queue.next()这上面

    Message next() {    
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }

    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    int nextPollTimeoutMillis = 0;
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }

        nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            if (msg != null && msg.target == null) {
                //遍历,查找队列中的下一个异步消息
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                if (now < msg.when) {
                    //下一条消息尚未就绪。设置超时以在准备就绪时唤醒。
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {                       
                    mBlocked = false;
              //这里就是做消息循环的关键代码了
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    msg.markInUse();
                    return msg;
                }
            } else {
                // 没有消息的时候就做如下设置
                nextPollTimeoutMillis = -1;
            }         
       }
}

至此,源码已经看完了,透过源码能够知道他内部执行是有个无限循环,而dispatchMessage不是根据Message的添加顺序,而是根据他的Message.when来判断是否执行当前的Message,Message设计其实是一个链表的结构,通过next不断的读取,其他应该没有什么难点了。。。
end

相关文章

网友评论

      本文标题:Handler源码分析

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