先上Handler的源码看一下:
-
-
-
-
-
-
-
- public Handler() {
- this(null, false);
- }
-
-
-
-
-
-
-
-
-
-
-
- public Handler(Callback callback) {
- this(callback, false);
- }
-
-
-
-
-
-
- public Handler(Looper looper) {
- this(looper, null, false);
- }
-
-
-
-
-
-
-
-
- public Handler(Looper looper, Callback callback) {
- this(looper, callback, false);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public Handler(boolean async) {
- this(null, async);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public Handler(Callback callback, boolean async) {
- if (FIND_POTENTIAL_LEAKS) {
- final Class<? extends Handler> klass = getClass();
- if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
- (klass.getModifiers() & Modifier.STATIC) == 0) {
- Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
- klass.getCanonicalName());
- }
- }
-
- mLooper = Looper.myLooper();
- if (mLooper == null) {
- throw new RuntimeException(
- "Can't create handler inside thread that has not called Looper.prepare()");
- }
- mQueue = mLooper.mQueue;
- mCallback = callback;
- mAsynchronous = async;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public Handler(Looper looper, Callback callback, boolean async) {
- mLooper = looper;
- mQueue = looper.mQueue;
- mCallback = callback;
- mAsynchronous = async;
- }
无聊的源码copy,可以看到最终都是调用的最后一个构造函数,Android源码里面到处都是这种写法,接下来我们要讲的sendMessage也是这种写法。这样写的好处是,我们不用关心过多的参数,灵活适配各种不同的需求。来看下初始化的三个属性,Looper:上面有说,Handler与创建它的线程的消息队列是绑定的,实际上Handler收发消息的三要素Handler、MessageQueue、Looper,是缺一不可的,线程必须有Looper,才能从MessageQueue里把消息取出来,所以一定要创建Looper才能使用Handler,刚刚的例子我们并没有看到Looper创建,而我们之所以能够在Activity里直接使用Handler是因为主线程,也叫UI线程、ActivityThread被创建的时候会初始化一个Looper。所以我们能够在UI线程里直接使用Looper(因为更新UI使用的多,而且Android整个窗口的UI更新都是用的Handler机制)。Callback:接口,回调用来写收到消息后处理消息的代码。async:传给消息的一个boolean型变量,是否需要同步。
直接来看我们最熟悉的sendMessage的方法:
- public final boolean sendMessage(Message msg)
- {
- return sendMessageDelayed(msg, 0);
- }
最普通的发送消息,其内部使用了延时发送,延时设为0. 这是Android里面常用的模式,这样做的好处是当你不需要传参数的时候可以直接使用无参的,使用方便,而且内部减少
了代码量,避免再重复写一个发送消息的实现。
-
-
-
-
-
-
-
- public final boolean sendEmptyMessage(int what)
- {
- return sendEmptyMessageDelayed(what, 0);
- }
发送一个空消息只需要传递一个信号,用消息类型就足够携带我们要传递的信息。同样调用了它的延时发送方法,延时为0.
-
-
-
-
-
-
-
-
-
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageDelayed(msg, delayMillis);
- }
我们可以看到,系统同样是通过发送Message对象来实现的发送空消息。这个对象值承载了我们设置的What信息。它最终调的也是 sendMessageDelayed(msg, delayMillis);延时发送一个消息。这里用了 Message.obtain();这是一种单例模式,避免每发送一个消息就new出一个对象,如果这样内存占用会很高,而且没有必要。在讲Message的时候会讲到。
-
-
-
-
-
-
-
-
-
- public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageAtTime(msg, uptimeMillis);
- }
这是一个定时在某个确定的时刻发送空消息的方法,内部同样调用了发送消息对应的方法。如果我们猜想的话,这个确定时刻发送同样可以用延时发送消息的方法来实现,只需要计算确定的那个时刻和当前时间的差值,然后把这个差值设为延时参数即可。后面来验证我们的猜想是否正确。
-
-
-
-
-
-
-
-
-
-
-
-
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- {
- if (delayMillis < 0) {
- delayMillis = 0;
- }
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
- }
看了这个方法,我们突然有一种被耍的赶脚,原来不是定时发送调了延时发送,而是延时发送内部调了定时发送,哈哈,这样也可以解释,因为他们本身就可以通过当前时间相互来转化。这里把当前时间加上延时时间,来计算要发送消息的时刻,最终用定时发送来实现。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
- MessageQueue queue = mQueue;
- if (queue == null) {
- RuntimeException e = new RuntimeException(
- this + " sendMessageAtTime() called with no mQueue");
- Log.w("Looper", e.getMessage(), e);
- return false;
- }
- return enqueueMessage(queue, msg, uptimeMillis);
- }
可以看到这个才是真正的发送了一条消息的方法,上面的所有发送消息的方法最终都是要调这个方法。在发送消息的最后又调用了这个enqueueMessage(queue, msg, uptimeMillis);从名字看,我们大概可以猜到,这里应该是把消息和消息确切的发送时间,塞到消息队列里面。稍有开发经验的都知道,把消息塞给队列这种事理论上应该交个MessageQueue来提供一个方法比较合理,Android为什么这么搞呢?我们带着这个疑问来看Handler提供的这个方法:
- private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
- msg.target = this;
- if (mAsynchronous) {
- msg.setAsynchronous(true);
- }
- return queue.enqueueMessage(msg, uptimeMillis);
- }
这里可以看到这里这个方法并没有做什么事,只是给Message的target属性赋值,表示这个消息的接收者是自己,这不就是Handler自己发消息给自己的判断标识么。。。mAsynchronous这个值是表示是否是同步的,是在Handler构造方法里传进来的。最后又把这个属性塞给了Message,让Message自己处理是否同步的问题。后面调了MessageQueue的enqueueMessage方法,到这里Handler消息的发送过程也就结束了。(多说一句,这里传的时间,其实是用来排序的,Message里面有一个long型的属性when,就是Message的时间标签,最终这里传入的uptimeillis会赋值给msg的when属性,让MessageQueue用来根据时间对所有插入Message进行排队,构成一个单链表。存放消息和循环用。为什么用链表,数据不停的再插入删除什么的操作,所以用链表,Android真屌,我平时都注意不到这些小细节,自己上去就乱搞。在MessageQueue的源码里可以看到这个过程,这里就不再讲述了,因为我们平常也不和MessageQueue直接打交道)
-
-
-
-
-
-
-
-
-
-
-
-
- public final boolean sendMessageAtFrontOfQueue(Message msg) {
- MessageQueue queue = mQueue;
- if (queue == null) {
- RuntimeException e = new RuntimeException(
- this + " sendMessageAtTime() called with no mQueue");
- Log.w("Looper", e.getMessage(), e);
- return false;
- }
- return enqueueMessage(queue, msg, 0);
- }
和这个和上面的方法基本一样就是设置了时间为0,表示在排队时把它塞到队列的最前端。不多讲了。
postRunnable的所有方法:
这里放一块儿说,可以明显看到,post系列的所有方法,立即post,定时post,延时post方法里面都是调用的sedMessage系列的对应的方法。而一个明显的标志就是Message参数都是把Runnable对象传给getPostMessage(r)返回了一个Message对象,如果没猜错,这货又是把Runnable赋给Message里面的一个Runnable属性。来看这个方法:
- private static Message getPostMessage(Runnable r, Object token) {
- Message m = Message.obtain();
- m.obj = token;
- m.callback = r;
- return m;
- }
就知道,果然不出所料,Message里面有一个叫callback的Runnable属性。这样是不是很完美呢,无论你send一个Message,还是post一个Runnnable,最终都是send一个Message。然后我把Runnable放到Message的Runnnable属性里面,接到Message再拿出来,就这么简单。
Handler发送消息的过程是向消息队列中插入一条消息,MessageQueue的next方法就会返回这条消息给Looper,Looper收到这条消息之后就开始处理了,最终消息由looper交由Handler处理,即Handler的dispatchmessage方法会被调用,这是Handler就进入处理消息的阶段。
1.一个Handler只有一个队列;
2.在调用Handler.post(Runnable runnable)方法时,会将runnable封装成一个Message;
3.在队列执行时,会判断当前是否封装了Runnable,如果封装了,就直接执行Runnable,如果没有,将当前的Message传递给handlerMessage(Message msg)处理;
4.Handler在实例化的时候可以设置一个callback<Handler.Callback>,callback也有一个HandlerMessage(Message msg)方法,如果步骤3中的Handler有callback,那么调用的是callback的HandlerMessage(message msg),否则调用自身的handlerMessage(Message msg)方法。
- private static dispatchMessage(Message msg){
- // 检查message的callback是否为null
- if(msg.callback!=null){
- handlerCallback(msg);
- }
- else{
- if(mCallback!=null){
- if(mCallback.handlerMessage(msg)){
- return;
- }
- handlerMessage(msg);
- }
- }
首先,检查Message的callback是否为null,不为空就通过handleCallback来处理消息。message的callback是一个Runnbale对象,实际上就是Handler的post方法所传递的Runnable参数。
- private static void handlerCallback(Message msg){
- message.callback.run();
- }
其次,检查mCallback是否为空,不为null即调用mCallback的handlerMessage方法来处理消息
- public interface Callback{
- public boolean handlerMessage(Message msg);
- }