最不墨迹的语言教你理解handler源码
近期打算出去面试找找工作,所以便要复习一下面试资料。看到handler的时候找了很多网上的文章,仔细阅读发现大部分文章往往都太过墨迹,把简单的事情写复杂。作为一个有多年android开发经验的老android我便决定用简单的语言描述一下Handler的工作机制,大家只需打开源码跟着我的思路便可以搞懂Handler
注:本文只适合有一定android基础的开发人员
##理解Handler的几个关键类
Handler:发送消息sendMessage
Message:异步消息的内容
MessageQueue:消息队列,用于存放异步消息
Looper:维持一个无限循环,轮询分发消息
这里我只讲解核心代码,一些不影响我们理解问题的部分大家自己学习
发送消息的时候方法的调用链条:handler发送一条消息(sendMessage)->sendMessageDelayed->sendMessageAtTime->enqueueMessage->queue.enqueueMessage
enqueueMessage:这个方法中会把Handler赋值给Message的target成员变量,也就是说message是持有他handler的引用的
queue.enqueueMessage:最终就是在Messagequeue方法中把消息添加到消息队列中的。
1、将消息放到队列中会有两种情况:(推送的消息为msg1,当前队列第一个消息为msg2)
- msg1.when==0或者msg1.when<msg2.when:这个方法中首先会判断推送过来的消息和当前队列第一个消息的执行时间,如果msg1.when==0或者msg1.when<msg2.when那么立即把msg1放到队列的头部。
- msg1.when>msg2.when :这种情况说明消息并不是第一个要被执行的消息,应该把消息插入到队列中合适的位置。所以会遍历队列,将msg1插入到合适的位置
2、Message:Message只作为我们传递消息过程中内容的载体,在这里不做深入讨论
3、MessageQueue:handler中的核心代码同 1
4、Looper:Looper是整个工作机制的核心。为了便于理解这里不做过多扩展,只讲解在主线程中Looper的工作方式。
Looper的准备和轮询状态是在ActivityThread类中的main方法完成的:Looper.prepareMainLooper();和Looper.loop();
先方法调用链条: Looper.prepareMainLooper->prepare(boolean)->sThreadLocal.set(new Looper(quitAllowed))->Looper.loop()
注意点:
sThreadLocal.set(new Looper(quitAllowed)) 创建一个新的Looper,这里重点关注Looper的构造方法。在Looper的构造方法中长久了一个消息队列MessageQueue并且获取了当前线程
Looper.prepareMainLooper方法中有一个同步代码块sMainLooper = myLooper();是为了避免重复创建Looper
重点说一下Looper.loop()这个方法:
在这个方法里面维持了一个死循环用于轮询消息。方法里面有个重要的方法msg.target.dispatchMessage(msg); (msg:Message rarget:Handler)这个方法用于分发消息,最终会把消息回调给Handler的Callback的handlerMessage方法(Handler本省的的handlerMessage也会被回调)
简单了画了一张图便于理解
理解handler源码最重要的两个方法Looper.loop()和MessageQueue.enqueueMessage()
理解了这两个方法基本上整个handler的工作机制就通了