美文网首页
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