前菜
介绍
Handler机制为Android提供给予开发者用于线程间切换,处理Java层消息与Native层消息的一种机制。
相关类
Java层
- Thread
- ThreadLocal
- ThreadLocalMap
- Looper
- Message
- MessageQueue
- Handler
Native层
- Looper
- ALooper
- NativeMessageQueue
- Message
- MessageHandler
- WeakMessageHandler
基础知识介绍
1. ThreadLocal
源码链接
https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/java/lang/ThreadLocal.java
https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/java/lang/Thread.java
类关系
public class ThreadLocal {
static class ThreadLocalMap {
private static final int INITIAL_CAPACITY = 16;
private Entry[] table = new Entry[INITIAL_CAPACITY];
static class Entry extends WeakReference> {
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);
value = v;
}
}
}
}
一般使用ThreadLocal例子,以Looper为例。
static final ThreadLocal sThreadLocal = new ThreadLocal();
...
sThreadLocal.set(new Looper(quitAllowed));
储存数据
public class ThreadLocal {
...
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);//第一次存储,该map一定为空
}
//从当前线程的 threadLocals 变量获取ThreadLocalMap对象
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
//创建ThreadLocalMap对象,并保存到当前线程的threadLocals变量中。
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
}
public class Thread implements Runnable{
...
ThreadLocal.ThreadLocalMap threadLocals = null;
...
}
ThreadLocalMap结构
static class ThreadLocalMap{
...
ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
private void set(ThreadLocal> key, Object value) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal> k = e.get();
if (k == key) {
e.value = value;
return;
}
//如果ThreadLocal被回收了,则也进行Entry数组的回收工作
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
}
读取数据
public class ThreadLocal {
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//第一次获取,map为空,直接走初始化方法
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
//如果之前没有保存过该ThreadLocal,则先存入一个null进入。
protected T initialValue() {
return null;
}
}
结论
- ThreadLocal 里面有一个静态内部类 ThreadLocalMap,ThreadLocalMap 有个静态类 Entry,Entry继承 WeakReference。
- ThreadLocal 是一个工具类,主要负责从当前 Thread 中操作 ThreadLocalMap。
- ThreadLocalMap 里面维护着一个 Entry 数组,每一个 Entry 对象都保存着一个以ThreadLocal 为key,Object 为value的结构。
- Entry 里面的key被封装为弱引用,便于释放回收处理。
- 在同一个线程中,ThreadLocal对象与Object进行组合,同一个ThreadLocal对象,在Entry中只能保存一个值。
2. epoll 机制
epoll 是 Linux 提供的高效访问 I/O 的机制。
1.使用epoll前,需要先通过 epoll_create 函数创建一个epoll句柄。
// 创建能容纳10个fd相关信息的缓存。
int epollHandle = epoll_create( 10 );
2.得到epoll句柄后,通过epoll_ctl 把需要监听的文件句柄加入 epoll 句柄中。
// 先定义一个event
struct epoll_event listenEvent;
// 指定该句柄的可读事件
// EPOLLIN(句柄可读)
// EPOLLOUT(句柄可写)
// EPOLLERR(句柄错误)
// EPOLLUP(句柄断)
listenEvent.events = EPOLLIN;
// epoll_event 中有个联合体叫data,用来存储上下文数据。
data.fd = listenEvent;
3.EPOLL_CTL_ADD将监听fd和监听事件加入epoll句柄的等待队列中。
// EPOLL_CTL_DEL 将监听fd从epoll句柄中移除。
// EPOLL_CTL_MOD修改fd的监听事件。
epoll_ctl(epollHandle, Epoll_CTL_ADD ,listener, &listenEvent)
4调用epoll_wait用于等待事件。
struct epoll_event resultEvents[10];
......
int timeout = -1;
while(1){
int nfds == epoll_wait(epollHandle,resultEvents,10,timeout);
// nfds 大于0表示所监听的句柄上有事件发生。
// nfds 等于0表示等待超时。
// nfds 小于0表示等待过程中发生了错误。
//
if(nfds == -1){
//错误
}else if(nfds == 0){
//超时
}else{
//resultEvents 用于返回哪些发生了事件的信息。
struct epoll_event &event = resultEvents[i];
if(event & EPOLLIN){
//收到可读事件
......
}
......//其他处理
}
}
//添加监听
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) ;
//处理监控请求
void Looper::pushResponse(int events, const Request& request) ;
正餐
Looper、MessageQueue、NativeMessageQueue创建过程
相关源码链接:
https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/java/lang/ThreadLocal.java
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/Looper.java
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/MessageQueue.java
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/Message.java
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/jni/android_os_MessageQueue.cpp
一般使用Looper,以ActivityThread为例。
public final class ActivityThread{
public static void main(String[] args) {
Looper.prepareMainLooper();
...
Looper.loop();
}
}
构建Looper对象
使用ThreadLocal工具保存到ThreadLocalMap中。
public final class Looper {
//ThreadLocal声明为静态对象,确保在同一个线程下,只有一个Looper对象存在。
static final ThreadLocal sThreadLocal = new ThreadLocal();
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对象,并将Looper对象保存到ThreadLocalMap中。
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));
}
//从ThreadLocalMap中获取Looper对象。
public static Looper myLooper() {
return sThreadLocal.get();
}
}
构建MessageQueue队列
public final class Looper {
final MessageQueue mQueue;
final Thread mThread;
...
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
public final class MessageQueue {
private final boolean mQuitAllowed;
private long mPtr;
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
//构造函数调用naitveInit,该函数由Native层实现。
//Native层的 NativeMessageQueue 对象引用指针。
mPtr = nativeInit();
}
}
构建Native层 NativeMessageQueue 对象
nativeInit 方法在 frameworks/base/core/jni/android_os_MessageQueue.cpp 定义实现。
class NativeMessageQueue : public MessageQueue, public LooperCallback {
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}
nativeMessageQueue->incStrong(env);
return reinterpret_cast(nativeMessageQueue);
}
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
//一个线程会有一个Looper循环来处理消息队列中的消息。
//获取保存在本地线程的存储空间的Looper对象
mLooper = Looper::getForThread();
if (mLooper == NULL) {
//如果第一次进来,则该线程没有设置本地存储,所以需要先创建一个Looper,然后后再将其保存到TLS中,
//这是很常见的一种以线程为单位的单利模式。
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
}
注册epoll机制
Looper::Looper(bool allowNonCallbacks)
: mAllowNonCallbacks(allowNonCallbacks),
mSendingMessage(false),
mPolling(false),
mEpollRebuildRequired(false),
mNextRequestSeq(0),
mResponseIndex(0),
mNextMessageUptime(LLONG_MAX) {
// Android 6.0 之前为 pipe, 6.0 之后为 eventfd
mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0, "Could not make wake event fd: %s", strerror(errno));
AutoMutex _l(mLock);
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
// 如果有新的epoll事件,则把原来的epoll事件关闭
if (mEpollFd >= 0) {
mEpollFd.reset();
}
// Allocate the new epoll instance and register the wake pipe.
// 创建一个epoll实例,并注册wake管道
mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
// 监听可读事件
eventItem.events = EPOLLIN;
// 监控的fd为唤醒事件fd
eventItem.data.fd = mWakeEventFd.get();
int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s",
strerror(errno));
// 如果请求队列中有数据,则还需要将请求中的事件注册到epoll实例中
for (size_t i = 0; i < mRequests.size(); i++) {
const Request& request = mRequests.valueAt(i);
struct epoll_event eventItem;
request.initEventItem(&eventItem);
// 注册请求中的事件到epoll实例中
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
request.fd, strerror(errno));
}
}
}
Handler
相关源码链接:
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/Handler.java
构建Handler
public class Handler {
final Looper mLooper;
final MessageQueue mQueue;
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Looper looper) {
this(looper, null, false);
}
...
public Handler(Looper looper,Callback callback) {
this(looper, callback, false);
}
public Handler(@Nullable Callback callback, boolean async) {
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());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
}
通过Handler发送Message
举个栗子
Handler mHandler = new Handler();
#1.1 发送空消息
mHandler.sendEmptyMessage(what);
#1.3 发送延时消息
mHandler.sendEmptyMessageDelayed(what, 0);
#2.1 发送Message对象
Message msg = Message.obtail();
msg.what = ...;
msg.obj = ...;
mHandler.sendMessage(msg);
#2.2 发送延时消息
mHandler.sendMessageDelayed(msg,1000);
#2.3 在指定时间发送消息
mHandler.sendMessageAtTime(msg,uptimeMillis);
#4. 发送Runnable消息
mHandler.post(Runnable r);
...
public class Handler {
//方式一
public final boolean sendEmptyMessage(int what) {
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
//方式二
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
//方式三
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
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) {
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) {
//这里将当前Handler进行保存,主要为了后续分发到对应 Handler 的对象的 handleMessage 方法。
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
}
MessageQueue处理逻辑
Message结构
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
Handler target;//发送该Message的对象,用于回调
Runnable callback;
Message next;
public long when;//执行时间
...
}
MessageQueue 与 Message 关系图
MessageQueue里面维护的是Message链表。
在Java层投递Message
public final class MessageQueue {
boolean enqueueMessage(Message msg, long when) {
......
boolean needWake;
synchronized (this) {
if (mQuitting) {
msg.recycle();
return false;
}
......
msg.when = when;
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
// 如果p为空,表明消息队列中没有消息,那么msg将是第一个消息,needwake需要根据mBlocked的
//情况考虑是否触发。
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//如果p不为空,表明消息队列中还有剩余的消息,需要将新的msg添加到对应的位置。
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
//从消息队列中取出消息,判断该消息的触发时间,与要新添加的Message的时间对比。
//如果新添加的Message时间小于 当前消息队列中获取的Message的时间,则直接break。
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//将新添加的Message添加到该队列的指定位置。如下图所示
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
//最后根据情况判断是否需要唤醒
if (needWake) {
// 调用nativeWake,以触发nativePollOnce函数结束等待。
nativeWake(mPtr);
}
}
return true;
}
}
在Java层提取Message
public final class MessageQueue {
Message next() {
......
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// ptr 保存了 NativeMessageQueue的指针,调用nativePollOnce进行等待
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) {
// Next message is not ready. Set a timeout to wake up when it is ready.
// 从消息队列中拿到的Message的执行时间,比当前时间还后面,则计算其差值,用于后面休眠。
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
//如果从消息队列中获取的Message小于当前时间,则返回给Looper进行派发和处理。
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;//断开引用链,便于GC回收
msg.markInUse();
return msg;
}
} else {
// No more messages.
// 消息队列中没有更多的消息了。则进行长时间休眠。
// -1代表长时间等待。
nextPollTimeoutMillis = -1;
}
......
// 下面主要IdleHandler的相关逻辑
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
//这里函数的返回值,觉得后续是否还会调用该IdleHandler的方法。
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
// queueIdle 返回false的时候,就会将其从ArrayList队列中移除掉,下次就不会再接收到函数调用。
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
}
nativeWake函数分析
nativeWake函数分析
frameworks/base/core/jni/android_os_MessageQueue.cpp
class NativeMessageQueue : public MessageQueue, public LooperCallback {
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr);
nativeMessageQueue->wake();
}
void NativeMessageQueue::wake() {
mLooper->wake();
}
}
system/core/libutils/Looper.cpp
void Looper::wake() {
......
uint64_t inc = 1;
//向管道的写端写入一个字符(旧版本是写入一个"W"字符)。
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
......
}
}
//旧版
//父进程、子进程
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ wake", this);
#endif
ssize_t nWrite;
do {
nWrite = write(mWakeWritePipeFd, "W", 1);
} while (nWrite == -1 && errno == EINTR);
if (nWrite != 1) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
}
}
nativePollOnce函数分析
frameworks/base/core/jni/android_os_MessageQueue.cpp
class NativeMessageQueue : public MessageQueue, public LooperCallback {
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr);
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
......
mLooper->pollOnce(timeoutMillis);
......
}
}
system/core/libutils/Looper.cpp
inline int pollOnce(int timeoutMillis) {
return pollOnce(timeoutMillis, nullptr, nullptr, nullptr);
}
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
timeoutMillis:超时等待时间。
如果为-1,则表示无限等待,直到有事件发生为止。
如果值为0,则无需等待立即返回。
outFd:用来存储发生事件的那个文件描述符。
outEvents:用来存储在该文件描述符上发生了哪些事件,目前支持可读、可写、错误和中断4个事件。(从epoll事件对应而来)
outData:用来存储上下文数据,这个上下文数据是由用户在添加监听句柄时传递的,它的作用和 pthread_create 函数的最后
一个参数 parame 一样,用来传递用户数据。
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) { //无限循环
// mResponses 为 Vector数据结构。
while (mResponseIndex < mResponses.size()) {
const Response& response = mResponses.itemAt(mResponseIndex++);
int ident = response.request.ident;
if (ident >= 0) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
if (outFd != nullptr) *outFd = fd;
if (outEvents != nullptr) *outEvents = events;
if (outData != nullptr) *outData = data;
return ident;
}
}
if (result != 0) {
if (outFd != nullptr) *outFd = 0;
if (outEvents != nullptr) *outEvents = 0;
if (outData != nullptr) *outData = nullptr;
return result;
}
result = pollInner(timeoutMillis);
}
}
int Looper::pollInner(int timeoutMillis) {
......
调用epoll函数等待,查看epoll函数返回结果;
超时、错误、有事件发生;
如果是管道读端有事件,则认为是控制命令,可以直接读取管道中的数据;(eventfd)
如果是其他fd发生事件,则根据Request构造Response,并push到Response数组中。
真正处理事件,首先处理Native的Message。调用Native Handler 的 handleMessage处理该Message。
处理Response数组中带有callback的事件。
}
Handler、Looper、MessageQueue、Thread关系
- 一个线程里面有一个Looper。
- 一个Looper对应一个MessageQueue。
- 一个Looper可能对应多个Handler。
- 相同的Looper的Handler发消息,都发送到同一个MessageQueue。
- MessageQueue处理完成后,分发消息会根据target字段,找到Handler的引用,并完成分发工作。
甜点
1. IdelHandler
public static interface IdleHandler {
boolean queueIdle();
}
当一个线程准备等待更多消息时,即其将消息分发完之后就会回调这个接口。
queueIdle返回false代表一次性,返回true可能有多次回调。
添加IdleHandler
public final class MessageQueue {
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
}
2. 消息屏障
Message类型分为3种类型:
- normal 普通消息
- barrier 消息屏障
- async 异步消息
插入消息屏障
public final class MessageQueue {
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
private int postSyncBarrier(long when) {
// 按照时间排序,将这个msg插入到消息队列中
synchronized (this) {
final int token = mNextBarrierToken++;
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
msg.arg1 = token;
Message prev = null;
Message p = mMessages;
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
if (prev != null) { // invariant: p == prev.next
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
}
消息屏障有6点注意事项!
- 没有设置target。
- 消息屏障也是带着时间戳的,也是按时间来进行排序,只影响后面他后面的消息。
- 消息队列是可以插入多个消息屏障的。
- 插入到消息队列的时候,是没有唤醒线程的。
- 插入消息屏障的时候会返回一个token,后续撤除这个消息屏障,需要使用token去消息队列中查找。
- 消息屏障没有对外开放,要使用需要利用反射机制。
移除消息屏障
public final class MessageQueue {
//根据token移除消息屏障。
public void removeSyncBarrier(int token) {
// Remove a sync barrier token from the queue.
// If the queue is no longer stalled by a barrier then wake it.
synchronized (this) {
Message prev = null;
Message p = mMessages;
while (p != null && (p.target != null || p.arg1 != token)) {
prev = p;
p = p.next;
}
if (p == null) {
throw new IllegalStateException("The specified message queue synchronization "
+ " barrier token has not been posted or has already been removed.");
}
final boolean needWake;
if (prev != null) {
prev.next = p.next;
needWake = false;
} else {
mMessages = p.next;
needWake = mMessages == null || mMessages.target != null;
}
p.recycleUnchecked();
// If the loop is quitting then it is already awake.
// We can assume mPtr != 0 when mQuitting is false.
if (needWake && !mQuitting) {
nativeWake(mPtr);
}
}
}
}
处理屏障
next方法里面处理,具体逻辑为:
public final class MessageQueue {
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
......
如果第一条消息是就是屏障,就往后面遍历查看是否有异步消息。
如果没有,就无限休眠,等待被别人唤醒。
如果有,就看这个消息触发时间还有多长,设置一个超时,继续休眠。
}
}
}
- 如果将消息插入到队列头部,不受消息屏障的影响,唤醒线程,去处理消息。
- 如果没有插入到队列头部,并且头部是消息屏障,此时插入普通消息不唤醒消息队列。
- 如果此时插入的是异步消息,并且插入的位置前面没有其他异步消息,则进行队列的唤醒。
Android中内存屏障使用例子
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/ViewRootImpl.java;l=1919?q=scheduleTrav&sq=
总结
- Java层提供了Looper类和MessageQueue类,其中Looper类提供循环处理消息的机制,以及插入、删除和提取消息的函数接口。
- Handler常用于用户与MessageQueue处理相关。
- MessageQueue内部通过mPtr变量保存了一个Native层的NativeMessageQueue对象。
- NativeMessageQueue保存了一个Native层的Looper对象,该Looper从ALooper派生,提供pollOnce 和addFd等函数。
- Java层有Message类和Handler类,而Native层也有对应的Message类和MessageHandler抽象类。