开始文章前先说一些废话吧,本来原先就打算写Handler消息机制了,可惜自己以各种理由拖着,最后只能强逼着自己把这个文章写完,好勒,不啰嗦了,开始正文吧。
Handler是Android提供给我们的一套消息机制,可以用来更新UI,也可以用来进行线程间的消息传递。
Handler的使用想必大家已经熟悉的不能再熟悉了,所以就不在多说。
先简单介绍一下涉及到的几个类:
Message:消息,在线程间进行通信的数据单元
MessageQueue:消息队列,主要功能是向消息池中添加消息和取走消息
Handler:处理消息事件,也将消息添加到消息队列中
Looper:不断循环遍历消息队列,分发给不同消息对应的Handler进行处理
再来一张图,帮我们理解下Handler的运行机制
接下来解释一下这张图:
1.Handler通过sendMessage方法发送消息,并调用enqueueMessage方法将消息加入到消息队列MessageQueue中。
2.Looper通过loop方法循环遍历消息队列,从队列MessageQueue中拿出消息Message,进行唤醒操作,然后调用Message对应的Handler里的dispatchMessage分发消息。
3.在Handler的handlerMessage方法中处理消息,这样就完成了一次消息的发送和处理过程。
Handler的运行机制大家稍微的了解了一下,接下来我们来看一下具体的代码实现,以下代码都是基于Android8.0的。
public final class Message implements Parcelable{
//用去区分不同的消息
public int what;
//消息所携带的数据
public int arg1;
public int arg2;
public Object obj;
//消息所对应的Handler
Handler target;
//回调方法
Runnable callback;
//下一条Message
Message next;
//消息池
private static Message sPool;
//消息池的大小
private static int sPoolSize = 0;
//消息池最大可以存放消息的个数
private static final int MAX_POOL_SIZE = 50;
...
//从消息池中取出Message
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool; //拿出消息池的队首消息
sPool = m.next; //将sPool指向下一个消息
m.next = null;
m.flags = 0;
sPoolSize--;
return m;
}
}
return new Message();
}
...
//回收消息,用于MessageQueue和Looper内部使用
void recycleUnchecked() {
...
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) { //当消息池存放的消息大于最大消息个数就不在存放了
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
}
Message通过next属性组成了一条单链表的结构,callback这个属性我们使用Handler进行post消息时会被赋值。
我们有时会用Message.obtain()来获取Message,从代码中可以看到从消息池中取出消息,返回给调用者,没有new一个返回给调用者。
...
//加入到消息队列中
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) { //msg必须与handler绑定,要不然会抛出异常
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) { //如果正在退出时,回收msg,加入到消息池
...
msg.recycle(); //recycle方法最终调用的还是recycleUnchecked
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
//p为null(代表MessageQueue没有消息) 或者msg的触发时间是队列中最早的还或者msg是立即要处理的
msg.next = p;
mMessages = msg;
needWake = mBlocked; //如果阻塞则进行唤醒
} else {
//needWake为ture的情况为阻塞状态并且p.target == null(我们自己发送的消息target是不能为null的,这个应该是系统发送的消息)还有就是msg为异步消息
needWake = mBlocked && p.target == null && msg.isAsynchronous();
//将消息按时间顺序插入到msg链表中
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr); //调用native层的唤醒操作
}
}
return true;
}
//获取下一个Message
Message next() {
final long ptr = mPtr;
if (ptr == 0) { //当native消息循环已经退出,则直接返回
return null;
}
int pendingIdleHandlerCount = -1; // 在第一次循环时pendingIdleHandlerCount才为-1
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//阻塞操作,当nextPollTimeoutMillis=-1时阻塞,当为0时表示不阻塞,当为其他时间表示延时
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//查询异步消息
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous()); //当不在是异步消息时,退出循环
}
if (msg != null) {
if (now < msg.when) {
//当消息触发时间大于当前时间,则设置延时时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
//获取一个Message
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg; //返回下一条消息
}
} else {
//没有Message则进行阻塞
nextPollTimeoutMillis = -1;
}
if (mQuitting) { //如果正在退出,则处理native层的消息队列,并返回null
dispose();
return null;
}
//在第一次循环是并且没有消息或者是一个延时消息
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
//继续循环并阻塞或者延时操作
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
//只有第一次循环时,才会被运行
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null;
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
//pendingIdleHandlerCount为0,下次将不再运行
pendingIdleHandlerCount = 0;
//当mPendingIdleHandlers操作完成以后,无需阻塞
nextPollTimeoutMillis = 0;
}
//移除消息
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
//循环遍历消息队列,移除连续的符合条件的消息
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
//再循环遍历剩下的消息,移除符合条件的消息
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
...
MessageQueue中唤醒的方法是nativeWake(),底层是epoll机制(一种IO多路复用机制),通过往pipe管道写端写入数据来唤醒线程工作。阻塞方法是nativePollOnce()方法,该方法会使线程释放CPU资源进入休眠状态,直到下个消息到达,才会被唤醒。
...
//初始化一个消息队列,并获取当前的线程,quitAllowed表示消息队列是否可以退出
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static void prepare() {
prepare(true);
}
//将当前的Looper与当前线程绑定,并且一个线程只能绑定一个Looper
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
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
//返回主线程的Looper
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
//循序遍历消息队列
public static void loop() {
final Looper me = myLooper(); //从ThreadLocal中取出当前线程绑定的Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); //取出消息队列中的下一条消息
if (msg == null) {
//没有消息则退出
return;
}
...
try {
msg.target.dispatchMessage(msg); //调用msg中的handler分发消息
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked(); //将msg存放到消息池中
}
}
...
Looper的prepareMainLooper在app一开始运行时,就在ActivityThread中被调用了,这也就是我们可以在主线程中直接创建一个Handler而不报错的原因,如果要在自己的线程中使用Looper,就要调用的Looper.prepare方法,将Looper与当前线程绑定。
...
//Handler构造方法
public Handler(Callback callback, boolean async) {
//匿名类、内部类或本地类用static进行修饰,要不然会提示警告
if (FIND_POTENTIAL_LEAKS) {
final Class extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//获取当前线程的Looper与Handler绑定
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//获取MessageQueue与当前Handler绑定
mQueue = mLooper.mQueue;
mCallback = callback; //会调用方法
mAsynchronous = async; //设置消息是否异步处理
}
//post消息
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
//获取callback被赋值的Message
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
//发送消息
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
//将消息加入到消息队列中
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true); //设置消息为异步消息
}
return queue.enqueueMessage(msg, uptimeMillis);
}
//消息的分发,在Looper中next方法中调用的
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //调用Message中的callback
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) { //调用Handler中的callback
return;
}
}
handleMessage(msg); //调用handleMessage方法
}
}
Handler有多个构造方法,最终调用的是Handler(Callback callback, boolean async) 这个构造方法。使用post发送消息时,会调用getPostMessage方法获取一个callback被赋值了的Message,然后调用sendMessageDelayed方法,而sendMessageDelayed最终调用的还是sendMessageAtTime这个方法。我们常用的sendEmptyMessage和sendEmptyMessageDelayed还有sendMessageDelayed方法最终调用的也是sendMessageAtTime这个方法。
下面这段代码是ActivityThread中Looper被初始化的代码
public static void main(String[] args) {
...
//主线程中初始化Looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//开始Looper循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
通过对涉及到的源码进行分析,我们可以知道:
1.每个线程中只能有一个Looper
2.每个Looper只有一个MessageQueue
3.Looper和Handler是在同一个线程中