Android学习笔记——从源码看Handler的处理机制

可能是出于性能的考虑,Android的UI操作是非线程安全的。

也就是说,如果你在一个新开的线程中直接操作UI是会引发异常的。

但是,Android又规定,不要去阻塞UI线程!否则,轻者引起程序卡顿,重者直接引发臭名昭著的“ANR”异常。

 

为了解决这一种矛盾,Android引入了Handler来解决这个问题。

Handler有两种常见的用法:

第一种是“发送信息”,我们可以将我们要改变的参数通过Message发送给指定的Handler,然后在Handler中的handleMessage方法中进行处理。

另一种是将一个runnable对象“post”给Handler对象去执行。

实际上,这两种方法是没有太本质的区别的。

接下来从源代码的角度来看Handler的整个运行机制。

首先先来看看Message对象:

message中有几个比较重要的成员变量

what // 一个用来表示这个信息的类型

arg1 // 参数1

arg2 // 参数2

object // 可以携带任何一个对象

还有这一个:

这个东东就是用来传递Runnable对象的。

 

接下来看Handler的sendMessage方法:

 

可以看到,它实际上是调用另一个发送的方法,我们跟进去:

 

靠,原来这几个方法是一回事来的,继续看:

 

终于不一样了~~~,这里多了一个MessageQueue对象,神马东西?从名字上看应该是“信息队列”的意思。也就是说,实际上,我们发送给Handler的信息并不是直接交给Handler去处理,而是Handler会把Message先放入一个MessageQueue中。MessageQueue就是一个数据结构,以队列的形式管理Message。那么,谁又把Message从Message从MessageQueue中拿出来呢?

这就需要另一个对象Looper了。

Looper的构造方法很有意思:

 

那也就是说我们是无法直接创建Looper对象的,经验告诉我们,这种情况下,一般不是单例就是工厂。实际上是这个:

 

这个方法保证了一个线程中只有一个Looper对象,否则会出现异常。

实际上,Looper中有一个loop方法:

 

上面是我把无关代码去掉后的loop方法,这个方法中looper对象一直去调用MessageQueue的next()方法,也就是不断地从消息队列中取出消息,然后重点来了:

 

嗯,这一步就是把消息交给对应的Handler去处理。

 

那么post一个Runnable对象又是怎么做到的呢?

 

这方法看起来相当的亲切啊!猜应该也可以猜到了getPostMessage方法是怎么实现了吧:

 

猜对没有?

所以本质上都是通过发信息来实现的。

看看dispatchMessage是怎么做的吧:

 

接下来就好说了,如果callback不是null,那就是让它去run咯!如果是普通消息, 那就是靠我们自己写的handleMessage去处理了。

 

至此,Handler的运行机制就是这些了。很喜欢张龙老师的一句话:源代码下,了无秘密。

总结一下:

Message:这个对象携带着我们想做的信息。

MessageQueue:以队列的形式管理Message对象。

Looper:每个线程只有一个Looper对象,它负责管理MessageQueue,会不断地从中取出Message对象,交给相应的Handler去处理。

Handler:它把Message发送给Looper维护的MessageQueue,并负责处理Looper传递过来的Message对象。

 

by yjiyjige 2013.06.19

posted @ 2013-06-19 21:51  孤~影  阅读(1429)  评论(0编辑  收藏  举报