题外话:
将近半载没有更新博客了。由于某些原因,这段时间自身的处境及对身边事物的看法发生了很大的变化。最近在看他人博客的时候产生了一些体会,写博客并不是为了写博客而写博客。自己以前写的博客质量都太低了,基本都是按照别人的思维方式复制一遍。实际上,这样的博客毫无意义。因此,从现在起博客更新频率会大幅度减少,但更多的将会是自己的研究与体会。那些网上满天飞的知识点,不再打算去整理了。Anyway,虽然我的博客没啥名气,我也不是什么大咖,但我享受写博客的乐趣,记录着我付出过的点滴——更重要的是,让更多的人看到我写的文章,那种分享的快乐难以言传。
Looper,Handler,Message,MessageQueue简介
Message:消息,信息传递的最小原子。其中包含了消息ID,并可选地包含了消息处理对象及回调等。由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
这四个类在Android起到了举足轻重的作用,几乎所有的线程通信都离不开他们。这正是Android县城设计的精妙之处。
线程阻塞:Looper
众所皆知,一个程序至少应当有一个线程,程序才得以保持。同理,程序是从main函数开始,且结束于main函数。因此,想要让程序得以保持,就要阻塞main线程。
Looper的字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。在程序开发中(尤其是GUI开发中,在Android中指的就是UI线程),我们经常会需要一个线程阻塞,一旦有新任务则执行,执行完后继续阻塞,直到有下一个任务,这就是Looper线程。使用Looper类创建Looper线程很简单:
public class LooperThread extends Thread {
@Override
public void run() {
// 将当前线程初始化为Looper线程
Looper.prepare();
// ...其他处理,如实例化handler
// 开始循环处理消息队列
Looper.loop();
// 从这里开始的代码将不会被执行,因为已经被Looper.loop()阻塞了
}
}
就这样,我们已经产生了一个Looper线程了。
Looper.prepare()
先看图:
通过上图可以看到,现在你的线程中有一个Looper对象,它的内部维护了一个消息队列MQ(MessageQueue)。注意!一个Thread只能有一个Looper对象。为什么呢?
public class Looper {
// 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
priva