}
…
msg.recycleUnchecked();
}
}
上面代码表示 loop 方法中执行了一个死循环,这也是一个 Android App 进程能够持续运行的原因。
注释1:不断地调用 MessageQueue 的 next 方法取出 Message。
注释2:如果 message 不为 null,则处进行后续处理。具体就是从 Message 中取出 target 对象,然后调用其 dispatchMessage 方法处理 Message 自身。target是谁?
Message.target
public final class Message implements Parcelable {
…
@UnsupportedAppUsage
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public long when;
/package/ Bundle data;
@UnsupportedAppUsage
/package/ Handler target;
@UnsupportedAppUsage
/package/ Runnable callback;
// sometimes we store linked lists of these things
@UnsupportedAppUsage
/package/ Message next;
/** @hide */
public static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
…
}
查看后其实就是个Handler。那咱们再看看Handler 的 dispatchMessage 方法
Handler.dispatchMessage()
/**
* Handle system messages here.
* 在这里处理系统消息。
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
/**
* Subclasses must implement this to receive messages.
* 子类必须实现它才能接收消息。
*/
public void handleMessage(@NonNull Message msg) {
}
可以看出,在 dispatchMessage 方法中会调用一个空方法 handleMessage,而这个方法也正是我们创建 Handler 时需要覆盖的方法。那么 Handler 是何时将其设置为一个 Message 的 target 的呢?
Handler.sendMessage()
Handler 有几个重载的 sendMessage 方法,但是基本都大同小异。咱使用最普通的 sendMessage 方法来分析,代码具体如下:
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
Handler.sendMessageDelayed()
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
Handler.sendMessageAtTime()
public boolean sendMessageAtTime(@NonNull 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);
}
经过几层调用之后,在这里我们拿到了在 ActivityThread 的 main 方法中通过 Looper 创建的 MessageQueue。
并且最后调用 enqueueMessage 方法将 Message 插入到消息队列 MessageQueue 中。
Handler.emqueueMessage()
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);
}
注释:将 Handler 自身设置为 Message的target(Handler) 对象。下来咱们看看 MessageQueue 的 enqueueMessage 方法。因此后续 Message 会调用此 Handler 的 dispatchMessage 方法来处理。
MessageQueue.enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
//注释1,非空判断
if (msg.target == null) {
throw new IllegalArgumentException(“Message must have a target.”);
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
//注释2,从这朝下都蛮重要的
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
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
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
< p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
注释1:会判断msg.target == null 没有设置,则直接抛出异常;
注释2:会按照 Message 的时间 when 来有序得插入 MessageQueue 中,可以看出 MessageQueue 实际上是一个有序队列,只不过是按照 Message 的执行时间来排序。
后续就是通过 ActivityThread 的 main 方法中 Looper 创建的 MessageQueue。Looper 从 MessageQueue 中取出 Message 之后,会调用 dispatchMessage 方法进行处理。
至此 Handler 的发送消息和消息处理流程已经介绍完毕。
重点关注
====
Handler 的 post(Runnable) 与 sendMessage(Message msg) 有什么区别
样例:
public class HandlerActivity extends ActivityBase{
ActivityHandlerBinding binding ;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
binding.tvTotle.setText(String.format(“哈哈哈哈考了%d”,msg.arg1));
break;
}
return false;
}
});
@Override
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHandlerBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.btnSendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = new Message();
msg.what=1;
msg.arg1=100;
handler.sendMessage(msg);
}
});
binding.btnPost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.post(new Runnable() {
@Override
public void run() {
binding.tvTotle.setText(String.format(“哈哈哈哈考了%d”,80));
}
});
}
});
}
}
Handler.post()
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage®, 0);
}
然后调用 getPostMessage() 传入 Runnable ,咱看看这个是干嘛的?
Handler.getPostMessage()
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
在这个方法中你会发现getPostMessage()会将 Runnable 赋值到 Message 的 callback 变量中,返回一个Message。并调用 sendMessageDelayed 方法。
Handler.sendMessage()
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
对比发现他们都调用 sendMessageDelayed() ,只不过生成的Message方式不同。 sendMessageDelayed() 上文已经讲到了就不多描述了。可以向上翻翻。
可以看出,经过几层调用之后,sendMessageDelayed() 最终会调用 enqueueMessage() 方法将 Message 插入到消息队列 MessageQueue 中。而这个消息队列就是我们刚才分析的在 ActivityThread 的 main 方法中通过 Looper 创建的 MessageQueue。
Looper 通过 loop() 方法从 MessageQueue 中取出 Message ,Message.target(Handrle) 会调用 dispatchMessage 方法进行处理。下面咱再看看它的源码。
Handrle.dispatchMessage()
/**
* Handle system messages here.
* 在这里处理系统消息。
*/
public void dispatchMessage(@NonNull Message msg) {
//注释1
if (msg.callback != null) {
handleCallback(msg);
} else {
//注释2
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
咱先看看handleCallback方法
Handrle.handleCallback()
private static void handleCallback(Message message) {
message.callback.run();
}
很明显,dispatchMessage 分两种情况:
注释1:msg.callback != null,一般为通过 post(Runnabl) 方式,会直接执行 Runnable 的 run 方法。因此这里的 Runnable 实际上就是一个回调接口,跟线程 Thread 没有任何关系。
注释2:msg.callback == null,这种一般为 sendMessage 的方式,则会调用 Handler 的 hanlerMessage 方法进行处理。
Looper.loop() 为什么不会阻塞主线程
刚才我们了解了,Looper 中的 loop 方法实际上是一个死循环。但是我们的 UI 线程却并没有被阻塞,反而还能够进行各种手势操作,这是为什么呢?在 MessageQueue 的 next 方法中.
MessageQueue.next()
Message next() {
// mPtr :used by native code
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//-1:仅在第一次迭代期间
int pendingIdleHandlerCount = -1;
//下一个Poll超时时间
int nextPollTimeoutMillis = 0;
for (;😉 {
if (nextPollTimeoutMillis != 0) {
//将当前线程中挂起的所有 Binder 命令刷新到内核驱动程序。
//在执行可能会阻塞很长时间的操作之前调用这会很有用,
//以确保任何挂起的对象引用都已被释放,以防止进程持有对象的时间超过它所需的时间。
Binder.flushPendingCommands();
}
//注释:重点来了。
nativePollOnce(ptr, nextPollTimeoutMillis);
…
}
}
MessageQueue.nativePollOnce()
/non-static for callbacks/
private native void nativePollOnce(long ptr, int timeoutMillis);
nativePollOnce 方法是一个 native 方法,当调用此 native 方法时,主线程会释放 CPU 资源进入休眠状态,直到下条消息到达或者有事务发生,通过往 pipe 管道写端写入数据来唤醒主线程工作,这里采用的 epoll 机制。下面是关于 nativePollOnce 的部分分析,参考了nativePollOnce函数分析,感兴趣的可以去自己看看,有点懵。等我再努力努力再来看这些吧。
epoll机制:提供了Linux平台上最高效的I/O复用机制。 从调用方法上看,epoll的用法和select/poll非常类似,其主要作用就是I/O复用,即在一个地方等待多个文件句柄的I/O事件。
nativePollOnce的实现函数是android_os_MessageQueue_nativePollOnce。
android_os_MessageQueue_nativePollOnce
frameworks/base/core/jni/android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
//取出NativeMessageQueue对象,并调用它的pollOnce
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
pollOnce()
frameworks/base/core/jni/android_os_MessageQueue.cpp
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
//重任传递到Looper的pollOnce函数
mLooper->pollOnce(timeoutMillis);
mPollObj = NULL;
mPollEnv = NULL;
if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
pollOnce()
system/core/libutils/include/utils/Looper.h
/**
* 等待事件可用,以毫秒为单位可选超时。
* 为发生事件的所有文件描述符调用回调。
* 如果超时为零,则立即返回而不阻塞。
* 如果超时为负,则无限期等待直到事件出现。
* 如果之前使用wake() 唤醒轮询,则返回POLL_WAKE
* 超时到期,没有调用回调,也没有其他文件
* 描述符已准备就绪。
* 如果调用了一个或多个回调,则返回 POLL_CALLBACK。
* 如果在给定之前没有数据等待超时,则返回 POLL_TIMEOUT。
* 如果等待过程中发生错误,则返回 POLL_ERROR。
* 如果文件描述符有数据,则返回一个 >= 0 包含标识符的值
* 并且它没有回调函数(这里需要调用者来处理它)。
* 在这个(并且只有这个)情况下,outFd、outEvents 和 outData 将包含投票
* 与 fd 关联的事件和数据,否则它们将被设置为 NULL。
* 此方法在完成调用适当的回调之前不会返回
* 用于所有已发出信号的文件描述符。
*/
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
inline int pollOnce(int timeoutMillis) {
//timeOutMillis参数为超时等待时间。如果为-1,则表示无限等待,直到有事件发生为止。如果值为0,则无需等待立即返回。
return pollOnce(timeoutMillis, nullptr, nullptr, nullptr);
}
pollOnce()
system/core/libutils/Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
//一个无限循环
for (;😉 {
//mResponses是一个Vector,这里首先需要处理response
while (mResponseIndex < mResponses.size()) {
const Response& response = mResponses.itemAt(mResponseIndex++);
int ident = response.request.ident;
if (ident >= 0) {
//首先处理那些没有callback的Response
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
“fd=%d, events=0x%x, data=%p”,
this, ident, fd, events, data);
#endif
if (outFd != nullptr) *outFd = fd;
if (outEvents != nullptr) *outEvents = events;
if (outData != nullptr) *outData = data;
//实际上,对于没有callback的Response,pollOnce只是返回它的ident,
//并没有实际做什么处理。因为没有callback,所以系统也不知道如何处理
return ident;
}
}
if (result != 0) {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - returning result %d", this, result);
#endif
if (outFd != nullptr) *outFd = 0;
if (outEvents != nullptr) *outEvents = 0;
if (outData != nullptr) *outData = nullptr;
return result;
}
//调用pollInner函数。注意,它在for循环内部
result = pollInner(timeoutMillis);
}
}
Handler 的 sendMessageDelayed 或者 postDelayed 是如何实现的
上面说到,在向 MessageQueue 队列中插入 Message 时,会根据 Message 的执行时间排序。而消息的延时处理的核心实现是在获取 Message 的阶段,接下来看下 MessageQueue 的 next 方法。
MessageQueue.next()
Message next() {
…
for (;😉 {
…