android之handler总结及Handler关键源码分析

什么是Handler

  官方文档中的说法是:一个Handler允许你发送或处理一个Message或Runnable对象。每个Handler实例都和一个单独的线程及此线程的消息队列关联。当你创建一个新的handler对象时它会绑定到那个创建它的线程及此线程的消息对列上。从这一点上来说,Handler会传递messages和runnables到与它关联的消息对列上,当它们出队时执行它们。

  文档中说Handler可以用来发送Message或Runnable,其实发送的都是Message,我们可以查看Handler的源码,找到PostXXX()方法,可以发现这此方法最终都会调用 sendMessageAtTime(getPostMessage(r), uptimeMillis);而其中的getPostMessage(r)方法的定义如下:

1 private static Message getPostMessage(Runnable r) {
2         Message m = Message.obtain();
3         m.callback = r;
4         return m;
5     }

可以看到:其实Post方法是用Runnable参数实例化一个Message然后再调用sendMessageAtTime方法发送到与此Handler关联的那个消息对列中。

主要作用

handler 主要有两个作用:1)安排或调度messages和runnables在将来的某个时间执行。2)将某个行为放到另外一个线程中执行。

其实,handler主要用在子线程与主线程之间的通信。当然也可用在子线程与子线程之间的通信。请看:android多线程与UI操作。在这里主要是想详细的总结一下与handler相关的知识点。

常用方法

    post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)
        以上post类方法允许你安排一个Runnable对象到与之关联的消息队列(一般是主线程)中等待执行,
        sendMessage类方法, 允许你安排一个带数据的Message对象到消息队列中,等待处理.

 源码分析

Handler关键源码
  1 public class Handler {
  2  
  3  //下面三个字段很重要,其实整个Handler都是在和它们打交道
  4     final MessageQueue mQueue;//消息队列,handler把消息投递到此队列
  5     final Looper mLooper;//消息循环
  6     final Callback mCallback;//提供了一个简便的处理message的方法
  7 
  8     //Callback interface you can use when instantiating a Handler to avoid having to implement your own subclass of Handler. 
  9     //此接口提供了一个简便的处理message的方法,可以使你在需要处理消息时避免一定要去重写handler类handleMessage方法。
 10     public interface Callback {
 11         public boolean handleMessage(Message msg);
 12     }
 13     
 14   //Handler的子类都应该去实现此方法,以达到自定义处理消息的行为
 15     public void handleMessage(Message msg) {
 16     }
 17     
 18   /**从名字大概能猜到它的作用:用来分发消息。其实从Looper的源码中可以看出此方法在Looper的loop循环中被调用。
 19   *第一个if判断此message中是否携带有Runnable,若有则直接执行之并返回,其实此if应该就是针对PostXXX方法设定的。
 20   *若没有则接着判断此消息对应的target即handler
 21   *是否实现了上面的Callback接口,若实现了,则直接执行之,再根据mCallback.handleMessage(msg)的返回值决定是否接着向下分发
 22   *若返回false,或mCallback为null则执行最后的handleMessage(msg);此方法就是我们继承Handler类要去重写的处理消息的方法
 23   /
 24     public void dispatchMessage(Message msg) {
 25         if (msg.callback != null) {
 26             handleCallback(msg);
 27         } else {
 28             if (mCallback != null) {
 29                 if (mCallback.handleMessage(msg)) {
 30                     return;
 31                 }
 32             }
 33             handleMessage(msg);
 34         }
 35     }
 36 
 37    
 38    //handler无参构造方法,此构造方法只能在主线程中用,因为只有主线程默认有looper
 39     public Handler() {
 40         this(null, false);
 41     }
 42 
 43  
 44  //此构造方法对应上面的Callback接口,通过此构造方法。我们可以不用继承Handler就能处理消息
 45     public Handler(Callback callback) {
 46         this(callback, false);
 47     }
 48 
 49     
 50     public Handler(Looper looper) {
 51         this(looper, null, false);
 52     }
 53 
 54   
 55     public Handler(Looper looper, Callback callback) {
 56         this(looper, callback, false);
 57     }
 58 
 59   
 60   /**Handler的一个隐藏构造方法供上面的几个构造方法调用。从中我们也可以看到构造一个handler
 61     *需要一个looper,一个此looper管理的消息队列mQueue,callback可有可无,async貌似和同步相关
 62     *
 63     */
 64     public Handler(Looper looper, Callback callback, boolean async) {
 65         mLooper = looper;
 66         mQueue = looper.mQueue;
 67         mCallback = callback;
 68         mAsynchronous = async;
 69     }
 70 
 71     //得到以此Handler为target的消息对象
 72     public final Message obtainMessage()
 73     {
 74         return Message.obtain(this);
 75     }
 76     //post方法用来传递一段代码到目的线程中执行,结合getPostMessage()
 77     //方法我们可以看出实际上Handler的postXXX()方法最终发送的也是Message对象
 78     //只是将Runnable封装到了Message中
 79     public final boolean post(Runnable r)
 80     {
 81        return  sendMessageDelayed(getPostMessage(r), 0);
 82     }
 83    //以r封装一个新的Message对象
 84    private static Message getPostMessage(Runnable r) {
 85         Message m = Message.obtain();
 86         m.callback = r;
 87         return m;
 88     }
 89     //sendMessageXXX()方法最终会调用enqueueMessage入队方法
 90      public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
 91         MessageQueue queue = mQueue;
 92         if (queue == null) {
 93             RuntimeException e = new RuntimeException(
 94                     this + " sendMessageAtTime() called with no mQueue");
 95             Log.w("Looper", e.getMessage(), e);
 96             return false;
 97         }
 98         return enqueueMessage(queue, msg, uptimeMillis);
 99     }
100 
101   //被sendMessageXXX()方法所调用,插入message到消息队列中
102     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
103         msg.target = this;
104         if (mAsynchronous) {
105             msg.setAsynchronous(true);
106         }
107         return queue.enqueueMessage(msg, uptimeMillis);
108     }
109 
110     public final void removeMessages(int what) {
111         mQueue.removeMessages(this, what, null);
112     }
113 
114 }

上面都是自己这几天上网查资料,接合自己读源码所悟,错误之处还请指正。

 

Handler的具体实例请参见:

android多线程与UI操作

posted @ 2013-04-19 15:58  g.hui  阅读(248)  评论(0)    收藏  举报