Handler postDelay 方法的一点思考
在ActivityThread类 中的main方法里面,我们可以看到这几行代码
ActivityThread
在prepareMainLooper
这个静态的方法中,我们会在当前线程中实例化一个唯一的Looper对象存入sThreadLocal中,因为 ThreadLocal这个变量是跟线程关联的,所以只要在当前线程中调用其get方法就会返回那个之前set的唯一的Looper对象,而我们在调用的Looper构造方法时,会初始化MessageQueue
Looper
当我们调用Looper.loop()时
Looper.
此处开启消息的读取,当队列为空或者队列中的头msg是一个在等待的延时msg,则此处会阻塞
在这里我们可以明显看到loop方法也是调用MessageQueque的next方法,由此可知,Looper对象主要负责MessageQueue对象的初始化,以及消息的读取
我们在来看看Handler 的初始化
Handler
我们可以看到其实例化的时候,会把当前线程中的looper,queue跟自己关联起来,当handler
通过sendMessage or postXXX
方法时,我们可以看到最后都会委托mQueue去enqueueMessage一个消息,所以handler
我们知道了,它主要负责消息的插入,以及消息被looper 对象读取后分发回调
我们可以重点看看MessageQueue中的消息插入和读取的方法
当我们插入一个队列中的第一个消息或者我们的消息比队列中第一个消息的延时时间还要短时,needWake
就会复制为mBlocked
,而mBlocked在队列被阻塞时其值会在next方法里面被置为true,至于next方法接下来的事情,我们稍后再看,needWake为true
调用 nativeWake
唤醒队列,队列取出第一个消息,如果是没有延时消息,则取出来分发,并把第二个消息取出来计算好剩下的延时时间(假设有延时),继续阻塞直至其剩下的时间耗尽,或者有新的头消息过来唤醒它,如果唤醒后取出的第一个消息是延时消息,则计算剩下时间继续阻塞直至其实时间耗尽自动唤醒,当我们post的新消息延时比头消息还长的时候,则会在遍历链表在一个合适的位置插入该消息,使队列中的消息按延时时间升序排列,一般情况并不需要唤醒被阻塞队列去check
消息