Handler机制详解
Handler运行机制梳理
我们在使用Handler的时候,往往是这样一个使用步骤:
初始化一个Handler对象,重写其handleMessage方法
获取一个Message对象,并相应的为其what、obj属性赋值
调用Handler.sendMessage(msg)方法发送消息
发送出来的消息,将在Handler的handleMessage方法中进行处理
因此,我们从sendMessage方法看Handler执行了什么逻辑:
frameworks\base\core\java\android\os\Handler.java
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
……
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
……
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;
}
由代码可知,sendMessage和sendMessageDelayed实际上都是调用了sendMessageAtTime方法。
若是采用sendMessage方法发送的消息,则uptimeMillis的值=当前时间;
若采用sendMessageAtTime方法发送消息,则uptimeMillis的值=当前时间 + delayMillis。
注意“msg.target = this;”这行代码,this在这里指的自然是发送这个Message的Handler对象,这行代码非常重要
最终,我们是通过“queue.enqueueMessage(msg, uptimeMillis);”这行代码将Message塞入了一个MessageQueue对象中,我们看看这个方法又做了什么:
frameworks\base\core\java\android\os\MessageQueue.java
final boolean enqueueMessage(Message msg, long when) {
……
synchronized (this) {
……
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
……
return true;
}
以上代码只做了一件事,将我们的Message加入到MessageQueue中,并根据when这个时间值对我们的MessageQueue中的Message进行了排序。
这个when值,就是之前我们传进来的那个uptimeMillis。
那么,消息被放到了我们的MessageQueue中,又由谁来取出并分发呢?
答案是我们的Looper。
我们的应用程序启动,主线程开启时,系统会创建一个Looper,并调用其loop方法,使其开始轮询MessageQueue中的消息:
frameworks\base\core\java\android\app\ ActivityThread.java
public static final void main(String[] args) {
……
Looper.prepareMainLooper();
……
Looper.loop();
……
}
frameworks\base\core\java\android\os\Looper.java
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
……
}
……
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
……
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
……
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
return;
}
……
msg.target.dispatchMessage(msg);
……
}
}
}
Loop方法实际上是维持着一个死循环,他不停的从MessageQueue中取到Message并将Message分发。
当MessageQueue中没有消息时,Loop会处于阻塞状态:
Message msg = queue.next(); // might block
Message被分发的代码为:
msg.target.dispatchMessage(msg);
这里的msg.target,即发送我们这个Message的Handler对象,因此,这行代码还是调用回了我们的Handler的dispatchMessage方法:
frameworks\base\core\java\android\os\Handler.java
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
代码可知,我们通过Handler发送的消息,最终由我们Handler的handleMessage方法来进行处理,Handler的这一套运行机制到此完毕。
Handler机制靠什么保证消息不混乱
假如现在我们new了几个Handler,同时去sendMessage,我们如何保证哪个Handler发送的消息,就交由哪个Handler的handleMessage方法去处理?
牢记我们发送消息和分发消息的时候的这2行代码:
frameworks\base\core\java\android\os\Handler.java
public boolean sendMessageAtTime(Message msg, long uptimeMillis){
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
……
return sent;
}
frameworks\base\core\java\android\os\Looper.java
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
return;
}
……
msg.target.dispatchMessage(msg);
……
}
}
}
通过这个“msg.target”,我们就可以保证:哪个Handler发送的消息,哪个Handler来处理。
ThreadLocal
ThreadLocal就是线程局部变量,经常使用此方法保存线程内的共享变量。
同一个线程内的多个不同的类,可以通过ThreadLocal来共享全局变量。
当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作。
所有在主线程new出来的Handler,最后都是通过ThreadLocal取用主线程创建的那个Looper,来实现的消息分发。
Handler机制中,我们通过ThreadLocal来保证一个线程中只有一个Looper。
Looper会阻塞主线程么
Looper是不会阻塞主线程的,正因为有Looper这个死循环,我们的app才能去即时的相应用户的操作。
不止是我们自己通过代码逻辑发送的Message,包括我们应用中所有的操作,比如开启一个Activity,调用Activity生命周期的方法:onCreate\onResume等,都是通过Handler发送消息,由Looper轮训到来处理的。
因此,Looper不会有阻塞我们的主线程。