Handler:Handler容许你发送而且处理和线程消息队列相关的消息(Message)和可运行对象。每一个Handler实例都有一个单独的相关线程和这个线程的消息队列。当你建立一个新的Handler时候,它将和建立者所在线程以及此线程的消息队列绑定。从这一刻起,它将传递消息和可运行对象到消息队列,并在消息和可运行对象被传出消息队列时执行它们。 java
Handler主要有两种用途:(1)把要被执行的消息和可运行对象添加到将要执行的任务清单里。(2)把要在另一条线程上执行的动做列入本身的队列。 ide
安排消息到任务清单,可使用如下几种方法:post,postAtTime(Runnable,long),postDelayed,sendEmptyMessage,sendMessage,sendMessageAtTime以及sendMessageDelayed方法。post版本的方法容许你安排Runnable对象到任务清单,这些Runnable对象将在消息队列接收到后调用它们。sendMessage版本的方法容许你安排一个Message对象到任务清单,这个Message对象包含一个将被Hanlder的handleMessage方法处理的数据包(须要在你的子类中实现handleMessage方法)。 oop
你在posting或者sending时,既能够容许消息循环在准备完成后当即处理任务,也能够在执行任务以前指定一个延迟时间。上述post和send系列的最后两个方法能够设置超时、空转和定时行为。 post
当你的应用程序建立一个进程的时候,这个进程的主线程就专门运行一个负责管理顶级程序对象(activities,broadcast receivers等等)和全部由这些对象建立的窗口的消息循环。你能够建立本身的线程,而且经过一个Handler和应用的主线程沟通。这样作跟以前调用post或者sendMessage同样,只不过是在你的子线程中调用的。给定的Runnable对象或者Message将被添加到Hanlder的消息队列,而且在适当的时候处理它们。 ui
Hanlder默认的构造方法,将这个Handler跟当前线程中的队列关联了起来: this
public Handler() { 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 = null; }
Handler必需要有一个消息队列,否则它无法接受消息。在线程初始化Handler以前,必须调用Looper.prepare(),详细内容请参考《Android之Looper》。 spa
初始化Handler时,还能够指定Looper和Callback,前者可使消息循环在Looper相关的线程中运行,后者可使你避免重写Handler。 .net
Handler的obtainMessage系列方法都是从全局的消息池中拿Message,若是池中没有,就new一个返回。 线程
post系列方法,都是封装的对应的send系列方法(将Runnable对象(msg.callback)和一个Object对象(即msg.object,若是有的话)经过getPostMessage方法拿到一个Message,而后send)。 code
private final Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; }
send系列方法,包装的都是sendMessageAtTime方法(sendMessageAtFrontOfQueue方法也是它的一个变种)。在sendMessageAtTime方法中,第一个参数是将被传递的Message对象,第二个是传递时的时间(能够猜测delayed系列方法都是当前时间加上延迟时间,事实证实这种猜测是正确的)。
public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
在这个方法中,将Message排入消息队列(队列中按照uptimeMillis排序,而sendMessageAtFrontOfQueue方法中将它设为0,因此sendMessageAtFrontOfQueue方法传递的Message将在Looper的loop方法循环的下一次循环中当即执行)。enqueueMessage方法的排序部分以下:
synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } }
将Message排入消息队列后的事情,是由Looper来完成的,详见《Android之Looper》中的loop方法。在Looper的loop方法中,调用了msg.target(即Handler,见sendMessageAtTime方法)的dispatchMessage方法。
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
第一个判断,msg.callback即为post系列方法传递到的Runnable对象。
private final void handleCallback(Message message) { message.callback.run(); }
第二个mCallback.handleMessage方法,可让你避免在本身的Handler子类中重写handleMessage方法。
还有remove系列方法,就是根据条件从消息队列中移除相关的Message。