1.Handle主要成员
1.1 Handler实例:负责消息的发送与回调,一个线程可以有多个Handler
1.2 Message:消息实例,保存消息并持有Handler实例,存在MessageQueue中,一个线程可以有多个Message。
1.3 MessageQueue:消息队列,存放Handler发送的消息,供Looper使用,一个线程只能有一个MessageQueue。
1.4 Looper:消息遍历者,持有MessageQueue,从MessageQueue中循环取出Message。一个线程只能有一个Looper。
2. 基本使用
//创建Handle
Handler handler = new Handler(getMainLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if(msg.what == 1){
//2.接收到消息,进行处理
}
}
};
//1.在需要的时候调用。发送消息
handler.sendEmptyMessage(1);
Handler使用我们一般就只需要做两步:发送消息与接收回调。接下去我们就沿着这两个来看源码。先看一下Handle的流程图。
3. Handle机制分析
3.1 发送Message
可以看到,不管调用handle的入口是哪个,最终的结果都是调用MessageQueue.enqueueMessage()方法。没什么好说的,唯一需要注意的就是long uptimeMillis在后面的队列中需要用到。
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg,
long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
//...
//这里需要注意一下uptimeMillis在后面队列排序中需要用到
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue,
@NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//不管从哪里开始,最终都会走到这里
return queue.enqueueMessage(msg, uptimeMillis);
}
接下来我们来看看MessageQueue里的enqueueMessage发生了什么。可以看到,mMessages其实就是Handle的消息队列了,mMessages作为队头,内部直接引用队列的第二项Message,然后第二项引用第三项,以此类推就形成了一个队列。举一个通俗的例子来说明,现在小明一家人排成一列(队列),爸爸在最前面(队头),爸爸牵着妈妈,妈妈牵着姐姐,姐姐牵着小明,小明...。
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
//...
//.....错误检查....
//...
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a
Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
//线程死亡,回收Message,不再往下执行
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
//直接拿到队头
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
//when就是我们前面说需要注意的时间uptimeMillis
//如果为0就是不延时,直接加入到队头
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
//循环找合适的位置插入到队列中。
//循环对比队列中每一项的延时时间,延时时间小
//就插入项的前面
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
//如果队列更改了,唤醒
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
3.2 取出Message
创建Handler的之前要先调Looper.prepare()创建Looper,然后创建Handler之后调Looper.loop()。我们来看一下主线程的Looper是在什么创建的,我们App的入口就是ActivityThread中的main函数,在main函数中创建Looper。
public static void main(String[] args) {
//其他的不看,只看Looper相关
//....
//创建主线程Looper
Looper.prepareMainLooper();
//创建主线程
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
//主线程的Handle
sMainThreadHandler = thread.getHandler();
}
//......
//直接调用loop
Looper.loop();
//主线程中Looper.loop死循环是不能退出的
//如果意外退出,说明程序有问题,直接报错
throw new RuntimeException("Main thread loop unexpectedly exited");
}
看看Looper中是怎么创建主线程的Looper。
public static void prepareMainLooper() {
prepare(false);
//加锁保证只创建一个Looper
synchronized (Looper.class) {
if (sMainLooper != null) {
//....
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//最终在这里创建了一个Looper
//子线程也是在这里创建Looper
sThreadLocal.set(new Looper(quitAllowed));
}
刚刚我们看到了线程创建的时候就直接创建了Looper,并调用loop()。现在来看一下loop()中的代码。在loop()中开启一个死循环,不断的轮询MessageQueue取出Message,Handler.dispatchMessage(Message msg)将消息发调用Looper持有的送给handler的回调handlerMessage();
public static void loop() {
final Looper me = myLooper();
//....
//拿到消息队列
final MessageQueue queue = me.mQueue;
//...
//开启死循环
for (;;) {
//拿到消息队列中需要的处理的消息
Message msg = queue.next(); // might block
if (msg == null) {
//没有消息了就退出循环进入休眠
return;
}
//......
try {
//msg.target就是Handle
//调用handle.dispatchMessage处理消息
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
//错误处理
}
//...
//回收消息
msg.recycleUnchecked();
}
}
刚刚看了loop()其实最终目的就是为了调用handle.dispatchMessage,接下来我们看一下handle.dispatchMessage做了什么。可以看到就是调用了handleCallback回调或者handleMessage回调。熟悉吗,就是我们创建Handle时的回调。
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
//回调1
handleCallback(msg);
} else {
if (mCallback != null) {
//回调2
if (mCallback.handleMessage(msg)) {
return;
}
}
//回调3
handleMessage(msg);
}
}
就这样,关于Handle的消息机制就完成了