越来越发觉handler的重要性,索性就总结一些。说到handler 就不能不说到Looper。
Looper:就相当于一个循环,每个thread会有一个。用ThreadLocal保存着Looper,如下所示:
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
所以很多时候,你看到各种例子里面,调用Looper.prepare() 就是初始化Looper。而在ui线程中会自动初始化。
Looper中有一个消息队列---MessageQueue 。 Handler 初始化的时候从本地的线程获得Looper。获得其消息队列。
Messenger 的使用:
在使用Message的时候,你会发现有个变量是Message.replyTo 其类型是Messenger 类型。
Messenger的解释就是信使。Messenger里面包含了一个handler。可以使用它发送消息。最后就是发送给Messenger里面包含的handler(mTarget)。个人的看法是,浅略地将是将Handler给封装了一下。但是其意义是不同了的,Message.replyTo 与接收到消息的handler 相互通信。
详细的例子以及参数解释可以参照:http://xwangly.iteye.com/blog/1109424
理解Messenger(Handler ) 与 Messenger(IBinder) 两个构造函数得到的mTarget(Handler 类型) 实际上是同一个Handler。
Handler 简单点理解就是往其所有的消息队列中添加消息,并且处理消息(message)。很多时候的使用就是干这两件事。handler的消息队列一般就是创建时所在的那个线程的消息队列。
handler 发送消息就是直接利用handler.sendMessage 之类的。
handler 处理消息 有很多方式。下面是Looper 中 处理消息部分的源代码,其实就是一个循环:
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg); //消息都是交给handler处理 ,所以具体处理部分就是在handler 的dispatchMessage 了。
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //消息的回调函数。 1.
handleCallback(msg);
} else {
if (mCallback != null) { //handler 的回调 2.
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); //Handler 自身的内部函数,可以重载 3.
}
}
从dispatchMessage就可以看到整个消息的处理过程。
1. msg.callback 消息自身的处理。如果设置了,就由消息自身去处理。 其实这个类型就是一个runnable 。只不过处理的时候 直接在ui线程运行。msg.callback.run() ; 这样就让它在ui上运行了。
所以我们在设置消息的时候,在消息发送的时候,就可以去设置消息处理的方式。Message 累本身没有函数去直接设置callback 但是 Message.obtain 有一个参数是Runnable 作为Message 的callback 的。
2.mCallback handler 设置的回调。 看一下handler 的构造函数就明白了:
/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*/
public Handler() {
this(null, false);
}
/**
* Constructor associates this handler with the {@link Looper} for the
* current thread and takes a callback interface in which you can handle
* messages.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*
* @param callback The callback interface in which to handle messages, or null.
*/
public Handler(Callback callback) {
this(callback, false);
}
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public Handler(Looper looper) {
this(looper, null, false);
}
/**
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
*/
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
自行设置就ok了(上面的构造函数只是handler中的一部分)。CallBack接口如下:
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
这是第二种处理方式。
3 第三种就是handleMessage 重载该函数即可。