Handler 和 Looper 是android 系统线程间协作的基础。
一个应用在主线程都有一个MainHandler 和 MainLooper,是由android 环境为其创建的,用户不必单独处理,直接拿过来用就可以。
在讲Handler Looper MessageQueue之前先说说handler和looper之间的联系和区别。
区别:
两者都和MessageQueue打交道,但Handler是向MessageQueue发送消息,这个发送是由Message来完成的,通过Message的sendToTarget()把消息发出去,然后调用handler的sendMessage(queue.enqueueMessage)。
Message msg = handler.obtainMessage();
msg.what = ... // 注意:msg.target 其实就是你传进来的handler实例
......
msg.sendToTarget();
在Message的sendToTarget()方法里,调用了Handler的sendMessage()方法,如下:
target.sendMessage(msg)
而Looper是从MessageQueue中取出消息(queue.next()).
联系:
1.Handler 依赖 Looper,每一个Handler必然有一个mLooper的成员变量。 Handler 的MessageQueue就是获取Looper的MessageQueue, 即Handler和Looper共享一个MessageQueue。在Handler的构造方法中有如下定义:
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;
由此可以看出,Handler对应两个实例,一个是Looper,一个是MessageQueue,但是MessageQueue其实就是Looper里的MessageQueue。
2.Looper取出MessageQueue在执行的时候(Looper.loop()方法,其实就是一个无限循环,死循环),实际上运行的是Handler的方法msg.target.dispatchMessage(msg)。
在loop()方法里,Looper取得mLooper实例,并获得MessageQueue,对MessageQueue做出队调用,如下:
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next();
msg.target.dispatchMessage(msg);
msg.recycle();
}
在继续下面的讲解之前在说说Looper和Thread之间的关系.
Looper依赖于Thread, Looper是一个消息循环体,在Thread中运行,从MessageQueue中取出下一条Message,分发到该消息的target, 即Handler。
Android系统启动一个Application的时候,会创建Main线程,也就是通常所说的UI线程,还有Looper,Handler,MessageQueue。即系统为用户创建UI线程的Looper和Handler还有MessageQueue。
但是如果当用户自己创建了一个Thread,就要自己去为该线程创建Looper,MessageQueue和Handler。
class LooperThread extends Thread {
public Handler mHandler;
@Override
public void run() {
Looper.prepare();// 这是为该线程创建Looper对象
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
注意: 1. new Handler(), 这个Handler是当前线程的Handler。
2.Looper.myLooper() 获得的是当前线程的Looper.
总结一下:消息处理机制主要是为异步刷新UI来设计的,当然异步刷新有如下几种方式:
1. Activity.runOnUiThread(Runnable)
2. View.post(Runnable)
3. View.postDelayed(Runnable, long)
4. Handler机制
这里主要是因为对UI的操作要求是Thread-safe, 非UI线程来完成View的刷新会出现各种问题。什么问题呢,仔细想想就知道了。
总结一:Message Looper Handler 实现
1. 初始化Handler实例, 设置 mLooper, mQueue。
Handler handler = new Handler();
2. 获取Message实例。
(1) Message msg = handler.obtainMessage(); // recommend
(2) Message msg = new Message();// 可以这样做,至于为什么可以,自己去想吧
3. 发送Message, 消息入队enqueue(msg)
msg.target = handler;
msg.sendToTarget();//其实调用的是target.sendMessage(msg), target = msg.target
target.mQueue.enqueue(msg);
4. Looper从MessageQueue取出下一个Message,去分发这个消息。
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
while(true) {
Message msg = queue.next();
msg.target.dispatchMessage(msg);
msg.recycle();
}
5. Handler去处理这个消息。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里会有一些不同,你一定很奇怪msg.callback是什么东西,不要紧,下面马上就要讲了,这里由于我们没有设置callback,所以必然为空,即msg.callback == null, 同样mCallback == null, 直接调用我们自己实现的handleMessage(msg)方法。
总结二:Message Looper Handler, Runnable 实现
1. 初始化Handler实例, 设置 mLooper, mQueue。
Handler handler = new Handler();
2. 生成Runnable接口,实现run()方法。
Runnable runnable = new Runnable() {
@Override
public void run() {
// process your job
}
}
handler.post(runnable);
这里要解释一下,Message对象的几个成员变量:
msg.what // message code to its handler
msg.target // handler
msg.data // similar to bundle (如果你不知道Bundle,请参考developer.android.com)
msg.callback // Runnable
好了,具体的请参看Message.java, 说道这里,应该很清楚了,虽然我们post出去一个Runnable,但是 Handler在后台为我们生成了一个Message对象,并且设置了callback,如下:
Message msg = handler.obtainMessage();
msg.callback = runnable;
3. 发送Message, 消息入队enqueue(msg)
msg.target = handler;
msg.sendToTarget();//其实调用的是target.sendMessage(msg), target = msg.target
target.mQueue.enqueue(msg);
4. Looper从MessageQueue取出下一个Message,去分发这个消息。
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
while(true) {
Message msg = queue.next();
msg.target.dispatchMessage(msg);
msg.recycle();
}
5. Handler去处理这个消息。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里由于msg.callback != null, 所以直接去调用handleCallback(msg), 如下:
private static void handleCallback(Message message) {
message.callback.run();
}
继续写下去:
Looper用于在android线程中进行消息处理,默认情况下, 一个线程并不和任何Looper绑定, 当我们调用Looper.prepare()时, 如果当前线程还没有和任何Looper绑定, 那么将创建一个Looper让他和当前线程绑定,当我们调用Looper.loop()时, 它将对当前线程所对应的Looper的Message进行处理,从MessageQueue中取出消息, 处理消息,一直循环,直到对该Looper调用quit()方法。
对于handler,其实只是把Message发送到对应的Looper的MessageQueue中,最后处理还是在Looper.loop()的死循环里。
一个Looper可以用于构造多个Handler, 因为Looper.loop()方法是个死循环,会让当前线程一直在那里处理消息,除非对该线程调用quit()方法。 所以,如果想对该Handler发送消息或者添加Runnable进行事务处理,要么在别的线程中进行,要么在该Handler的handleMessage()方法或者Runnable的run()方法中操作。
注意:
Handler的构造函数Handler() 和 Handler(Handler.Callback callback) 虽然没有looper参数,但是它实际上市通过Looper.mylooper()来获取当前线程的Looper的。