源码学习
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//TODO Handler your Message
}
}
我们在定义使用 Handler时,通常如上所写,先查看Handler的构造函数:
final MessageQueue mQueue;
final Looper mLooper;
public Handler() {
...... //省略了 Handler class 是不是 static or leaks 的检测代码
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的构造函数中做了如下事情:
-
mLooper = Looper.myLooper();
获取Looper对象 -
mQueue = mLooper.mQueue;
从Looper中获取MessageQueue对象
既然 Handler 、MessageQueue 都与 Looper 有关连,先看下Looper的内容:
//当前线程对象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//获取当前线程绑定的Looper对象
public static Looper myLooper() {
return sThreadLocal.get();
}
//创建一个Looper对象绑定到当前线程
//并在prepare的注解中,我们知道Looper的执行过程 prepare() -> loop() -> quit() ,后面跟着这个流程解析
public static void prepare() {
//当前线程只能绑定一个Looper对象
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//当前线未绑定Looper对象,则创建 Looper对象并绑定到当前线程
sThreadLocal.set(new Looper());
}
//Looper 的构造函数是默认构造函数
private Looper() {
//创建了一个MessageQueue
mQueue = new MessageQueue();
mRun = true;
//绑定了当前线程
mThread = Thread.currentThread();
}
在Looper中:
- 绑定当前线程创建Looper对象,且当前线程只能绑定一个Looper对象
- 并创建了MessageQueue 对象,即Looper对象中绑定了MessageQueue对象
现在查看 loop() 方法,它是一个静态方法
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
//获取当前线程的Looper对象
Looper me = myLooper();
//不存在,则抛出异常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取绑定的消息队列
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();
//注意:这里有一个死循环,不断从消息队列中取消息
while (true) {
//从消息队列中取消息 (Message下面解析)
//这个过程可能会阻塞
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
long wallStart = 0;
long threadStart = 0;
// This must be in a local variable, in case a UI event sets the logger
//打印log
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}
// 这里开始分发消息, msg.target ? (查看其类型就是 Handler类型,从哪里赋值的呢?后面解析)
msg.target.dispatchMessage(msg);
//打印log
if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}
// 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();
}
}
}
在loop() 中,
- 在Looper 中有一个 死循环,会不断的从消息队列中取消息、并通过Message绑定的Handler分发消息。
(我们知道Android中屏幕会不断的被渲染,这其实就是原因)
Message 对象,很简单就是定义了消息的几个变量和绑定的Handler等
public class Message{
public int what;
public Object obj;
Handler target;
......
}
从上面我们,我们可以看到 消息的一个分发的过程,现在我们来发送消息,了解消息是如何被添加到 MessageQueue(消息队列),消息的 target(Handler 消息处理)从何而来。
//从上面 Handler定义中继续,发送一个空消息
mHandler.sendEmptyMessage(1)
我们查看上处代码的源码
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
//定义了一个默认Message变量
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
...//执行到如下方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
//当前线程绑定的Looper,此Looper绑定的MessageQueue
MessageQueue queue = mQueue;
//判断消息对列是否为空,不为空,将消息添加入队列中
if (queue != null) {
//此处将 当前Handler 绑定到Msg中
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;
}
从以上代码,可以知道:
1. 分发处理 Message 的Handler 就是 发送此消息的Handler
至于消息的处理 Handler.handlerMessage(msg) 何时被调用,如下:
//在消息的分发后被处理
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
总结 Looper、MessageQueue、Handler 和 Message 的关系如下:
当我们调用handler.sendMessage(msg)方法发送一个Message时,Message会绑定此Handler,然后Message被发送到 与当前线程绑定的Looper的MessageQueue中。当前线程绑定的Looper将会不断的从绑定的MessageQueue中取出新的Message,通过Message绑定的Handler 进行消息分发,在与Message绑定的handler的 handleMessage()方法中处理此消息。
- 一个Thread对应多个Handler
- 一个Thread对应一个Looper和MessageQueue,Handler与Thread共享Looper和MessageQueue。
- Message只是消息的载体,将会被发送到与线程绑定的唯一的- MessageQueue中,并且被与线程绑定的唯一的Looper分发,被与其自身绑定的Handler消费。