Android Message机制
Android的Message机制,也叫handler机制,主要由3部分+Message组成,这三部分分别是Looper、MessageQueue和Handler。
Looper:循环体,其作用就是从MessageQueue中取出Message进行消费,一般线程的主体方法的结尾,都会调用Looper的loop方法进入循环,等待处理消息。
MessageQueue:Message的管理队列,用于保存Message。
Handler:Message处理的句柄(具体的处理操作)。
Looper
一般支持Message机制的应用进程或线程,都会调用Looper,如SystemServer和ActivityThread。
我们先看以下Looper是如何创建。
Looper的创建
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
Looper.prepareMainLooper();
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
以上的代码段是ActivityThread.main方法中对Looper相关代码的提取,可以看到,使用Looper只需简单的两个方法:prepareMainLooper和loop。
prepareMainLooper是Looper的静态方法,用于创建主线程的Looper对象,从名字上来看,除了主线程,子线程也是可以创建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();
}
}
public static void prepare() {
prepare(true);
}
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.prepareMainLooper主要是调用了prepare方法,传参false,表示创建一个不可退出的Looper,这个Looper主要是应用主线程的Looper,由于应用的主线程是不能退出的,主线程的Looper一般都会在主线程的主体结束前调用loop方法,使应用进入循环,保证主线程不会退出,而一旦主线程退出,则应用也就退出。而Looper同时为应用子线程提供了无参的prepare方法,无参的prepare方法就是调用了私有方法Boolean类型的prepare方法,传参true,表示该Looper可退出。
prepareMainLooper会将创建出来的Looper保存到sMainLooper中供应用其他的子线程快速获取。
带参prepare方法中会判断线程是否已经创建过Looper,Android只允许每个线程有一个Looper,这个是合理的设计,因为每个线程最多只能无限执行一个循环。
带参prepare方法中,使用了ThreadLocal泛型类型,以支持每个线程都能创建Looper,ThreadLocal有一个数组保存了每个线程的Looper对象,在不同的线程中调用sThreadLocal.get()获取的Looper都是不一样的。具体可参考libcore/ojluni/src/main/java/java/lang/ThreadLocal.java 。
Looper实例的构建比较简单,主要是创建了MessageQueue实例和记录当前的Thread对象,这里就不展开说明。
Looper.loop
Looper.loop是整个Looper的核心,我们在这里分析整个loop的过程,了解这当中的细节。
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g.
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// Make sure the observer won't change while processing a transaction.
final Observer observer = sObserver;
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
if (thresholdOverride > 0) {
slowDispatchThresholdMs = thresholdOverride;
slowDeliveryThresholdMs = thresholdOverride;
}
// logSlowDelivery和logSlowDispatch是处理dispatch和delivery较慢的消息。
final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
final boolean needStartTime = logSlowDelivery || logSlowDispatch;
final boolean needEndTime = logSlowDispatch;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
Object token = null;
if (observer != null) {
token = observer.messageDispatchStarting();
}
long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logSlowDelivery) {
if (slowDeliveryDetected) {
if ((dispatchStart - msg.when) <= 10) {
Slog.w(TAG, "Drained");
slowDeliveryDetected = false;
}
} else {
if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
msg)) {
// Once we write a slow delivery log, suppress until the queue drains.
slowDeliveryDetected = true;
}
}
}
if (logSlowDispatch) {
showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
loop方法中代码很多,但很多都是非重点代码,都是一些调试log的代码,真正的核心代码只有以下2行:
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg);
loop就是进入一个死循环体中,不断地从MessageQueue中取出Message进行消费,消费就是调用Message中的target(Handler)的dispatchMessage方法进行处理。
Looper中的设计特点
Looper中有一些设计是非常妙的,我们来总结一下。
1.Looper的构造方法是private修饰的,意味着,外部无法实例化Looper,只能通过Looper类提供的静态方法进行创建,类似于单例模式。
2.Looper中使用的设计模式又并非单例模式,因为一个进程中,是允许有多个Looper实例对象的。
Message和Handler
MessageQueue的代码更为复杂,我们先来看看MessageQueue的数据是怎么使用的。
我们以ActivityThread内部发送Message的源码来进行抛砖引玉。
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
ActivityThread的sendMessage方法中,主要是通过Message.obtain()方法生成一个空的Message,然后填充what字段(必须)以及其他选填数据,最后通过Handler的sendoMessage方法发送消息。值得注意的是,Message中有setAsynchronous方法,表明Message的处理或者分发应该支持异步的操作。
Message的发送在这里我们重点关注2点:①Message的创建方式有多少种,里面有什么重要的信息。②Handler发送Message的方式有多少种,以及发送Message的过程是怎样的。
Message的创建
我们先来看看Message的类图:
Message中构造函数是public修饰的,表明其可以外部new出对象,但Message类提供了多个obtain的静态重载方法。其中主要看它们的参数,有几个重要的参数组合,无参方法表示只new出一个纯粹的Message对象,需要用户自行填充数据。带有Message对象参数的方法,将obtain一个Message,然后将参数Message中的数据copy到新的Message中。剩下的几个就是赋予不同参数的obtain方法,将这些参数赋值到Message的变量中。
其中有几个比较重要的变量:what(Message的类型,识别Message的重要变量)、arg1和arg2(Message的参数,可不设置)、obj(传递的一些数据对象)、flag(一些标志,如异步)、target(Handler,处理Message的一种方式)、callback(Runnable,处理Message的一种方式)、next和sPool(Message的缓存池,在一个进程中,Message并不是每次都会new出新的对象,以减少内存的开销)。sendToTarget方法,用于Message的发送。
Message的设计特点
Message中使用了缓存池的设计思想,是值得我们思考和参考的,我们来具体看一下。
Message的多个obtain方法,都会调用到无参的obtain方法,而无参的obtain方法就是使用缓存池的核心。
public static Message obtain() {
synchronized (sPoolSync) { //持锁,保证申请/创建Message对象是原子操作
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
Message中的缓存池使用的是单链表的方式实现,sPool就是这个链表的表头,next就是指向下一个节点的指针,当调用obtain时,如果sPool非空,即缓存池中有Message实例对象时,则可直接获取该对象来使用,同时将这个实例对象的next指针赋值给sPool,此时这个实例对象就从缓存池中被取出。这个缓存池的大小是MAX_POOL_SIZE(50),那么这缓存池中的实例对象时从哪来的呢?其来源就是当Message被处理完后,调用recycleUnchecked,丢到缓存池中备用:
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
recycleUnchecked的前半部分都是将Message实例的数据reset,如果目前缓存池的数量已经达到上限,则抛弃这个实例,由虚拟机的GC进行回收,否则加入到缓存池的链表头中,等待obtain方法被调用时再次使用。
Handler的消息发送
Handler的类图如下:
Handler的作用主要是分发消息和处理消息,同样,也可以通过Handler来实例化Message对象。我们主要关注Handler的一下方法:
1.post系列方法,用于发送消息,实际上底层也是调用到sendMessage。
2.sendMessage系列方法,用于发送消息。
3.dispatchMessage,分发消息。
4.handleMessage,处理消息,Handler默认空实现,用户一般会实现一个继承Handler的子类,重写handleMessage方法,进而处理消息。
5.removeMessages和removeCallbacksAndMessages,用于删除指定的一类消息。
post
我们先来看一下post系列的方法,以两个典型为例看一下;
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
Handler的post方法和postAtTime方法,传参都是Runnable类型的实例,postAtTime则是添加了事件戳,两者的底层都是调用到sendMessage系列的方法。而post系统发送的消息,由getPostMessage方法来生成。从post系列的方法中可以看到,post的Message的处理都是Runnable的方式。
sendMessage
我们再来看看sendMessage方法的实现,这个是我们的重点方法,我们也还是以两个典型方法来分析:
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;
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);
}
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
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, 0);
}
不论是sendMessage、sendMessageDelay、sendMessageAtTime或者sendMessageAtFrontOfQueue,其最终都是调用enqueueMessage方法将Message压入到MessageQueue中:
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);
}
其中Message在MessageQueue中的位置是由uptimeMillis参数来决定,MessageQueue中的Message是由消息处理的时间戳来排序的,因此sendMessageAtFrontOfQueue方法中,uptimeMillis为0,表示立即处理。至于Message是如何压入到MessageQueue部分的逻辑,我们放到MessageQueue的代码中进行分析。
dispatchMessage
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
dispacthMessage的逻辑十分简单,如果Message有设置自身有设置callback(Runnable实例),则执行运行callback。否则会交由Handler进行处理。Handler在构造的时候可以传入Callback实例,这样就会优先使用Callback来进行处理,如下:
// frameworks/base/core/java/android/view/LayoutInflater.java
mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == MESSAGE_BLINK) {
if (mBlink) {
mBlinkState = !mBlinkState;
makeBlink();
}
invalidate();
return true;
}
return false;
}
});
否则就调用handleMessage方法,一般由用户自定义实现,如下:
// frameworks/base/wifi/java/android/net/wifi/WifiManager.java
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
WifiManager manager = mWifiManager.get();
if (manager == null) {
Log.w(TAG, "LocalOnlyHotspotCallbackProxy: handle message post GC");
return;
}
switch (msg.what) {
case HOTSPOT_STARTED:
WifiConfiguration config = (WifiConfiguration) msg.obj;
if (config == null) {
Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null.");
callback.onFailed(LocalOnlyHotspotCallback.ERROR_GENERIC);
return;
}
callback.onStarted(manager.new LocalOnlyHotspotReservation(config));
break;
case HOTSPOT_STOPPED:
Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped");
callback.onStopped();
break;
case HOTSPOT_FAILED:
int reasonCode = msg.arg1;
callback.onFailed(reasonCode);
Log.w(TAG, "done with the callback...");
break;
default:
Log.e(TAG, "LocalOnlyHotspotCallbackProxy unhandled message. type: "
+ msg.what);
}
}
};
Message是怎么走到Handler的?这个可以往前参考Looper.loop和Handler.enqueueMessage,enqueueMessage将Message的target变量设置成Handler的实例,在Looper中的loop方法,从MessageQueue中取出Message后就会调用其target变量的dispatchMessage方法,这样就走到了这里来。
removeMessages方法比较简单,主要跟MessageQueue相关,我们放到MessageQueue的分析时再看。
MessageQueue
MessageQueue是Android Message机制的核心,也是最复杂的部分,我们仔细分析一下这里。下面是MessageQueue的类图:
MessageQueue的代码涉及了Java部分和native部分,我们还是分几条主线来进行分析:
1.MessageQueue的创建。
2.消息的来源 – enqueueMessage
3.消息的分发处理
4.消息的remove
5.设计特点
MessageQueue的创建
再Looper的创建的时候已经看到,MessageQueue的实例就是在Looper的创建时创建的:
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
MessageQueue跟Looper是绑定的,一个Looper有一个MessageQueue。在主Looper中,MessageQueue的mQuitAllowed为false,非主Looper则可为true。nativeInit是native的方法:
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<jlong>(nativeMessageQueue);
}
MessageQueue在构造时会创建一个native层对应的实例 – NativeMessageQueue,然后将这个实例的native地址返回。下面是NativeMessageQueue以及相关类的类图:
NativeMessageQueue以及其相关的类跟Java层的MessageQueue和Looper是不是十分的像。接下来的内容与就是分析native层的内容。
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
NativeMessageQueue在构造时就会获取/创建一个native层的Looper实例,而这个实例是绑定线程的,也就是说,一个线程只能有一个native层的Looper实例,这与Java层的Looper是一样的。native层的Looper从名字上来看,其就是一个消息的驱动器,用于消息的运转。
Looper::Looper(bool allowNonCallbacks)
: mAllowNonCallbacks(allowNonCallbacks),
mSendingMessage(false),
mPolling(false),
mEpollRebuildRequired(false),
mNextRequestSeq(0),
mResponseIndex(0),
mNextMessageUptime(LLONG_MAX) {
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();
}
Looper实现中有两种文件:eventfd和epoll_fd。eventfd用于唤醒Looper,epoll_fd则是用于监听消息。event_fd由eventfd方法创建,epoll_fd由rebuildEpollLocked方法创建:
void Looper::rebuildEpollLocked() {
// Close old epoll instance if we have one.
if (mEpollFd >= 0) {
#if DEBUG_CALLBACKS
ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
#endif
mEpollFd.reset();
}
// Allocate the new epoll instance and register the wake pipe.
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;
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));
for (size_t i = 0; i < mRequests.size(); i++) {
const Request& request = mRequests.valueAt(i);
struct epoll_event eventItem;
request.initEventItem(&eventItem);
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));
}
}
}
rebuildEpollLocked将mWakeEventFd加入到mEpollFd的监听队列中。还有mRequests的文件描述符,但在常用的Message消息处理中并没有使用到,我们在本文档的最后一章使用NetworkStack的例子来进行分析。本章则先跳过。
至此,MessageQueue已经在native层构建好了一个Message驱动的框架。
消息的来源 – enqueueMessage
Message的发送在前面Message和Handler的一章中已经分析过,Message的sendToTarget方法、Handler的post和sendMessage系列方法,都可以发送Message,其最终都是调用到MessageQueue的enqueueMessage方法:
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
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) {
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();
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 {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
MessageQueue对Message的管理使用的是单链表结构,mMessages就是这个链表结构的链表头。从上述代码上看到,enqueueMessage分了两类情况:
1.将Message压入到链表头中。
1).当前的链表已经没有数据(mMessages为null)。
2).enqueue的Message的时间戳为0,表示当前立即处理的消息。
3).enqueue的Message的时间戳比链表头的Message的时间戳更为早(链表中Message的排序是按照时间戳的顺序进行排序,链表头的Message时间戳必定是最早的)。
这种情况下needWake的值为mBlocked,表示如果当前MessageQueue正处于阻塞状态,则需要唤醒以检查是否已有需要处理的Message。
2.为Message排序,将其插入到链表中合适的位置。
这种情况下needWake的值是根据链表中表头Message和当前Message以及插入位置的前一些Message的属性来确定。
1).如果当前queue不是阻塞状态,则无需唤醒queue,needWake为false。
2).如果queue处于阻塞状态,且表头的Message没有Handler。但从Handler的enqueueMessage方法中可以看到,正常使用这是不可能发生的,除非是我们自己修改的。
3).当前的Message是异步的。满足以上3点,则neddWake为true。
4).如果前面三点都符合,needWake的值为true,但再插入Message的过程中,发现插入位置前的Message是异步的,这是由于异步的性质决定的。我们在后面分析一下这个异步会带来什么行为。
经过前面的插入到链表的操作后,如果needWake为true,则调用nativeWake方法,最后调用到native层的Looper对象的wake方法。
void Looper::wake() {
uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
}
Looper.wake会往mWakeEventFd文件节点中写入值,以唤醒Looper的epoll。
消息的分发处理
在Java层的Looper.loop分析中,得知Looper分发事件的Message来源是通过MessageQueue.next()方法来获取。
Message next() {
final long ptr = mPtr;
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
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.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a 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 {
// No more messages.
nextPollTimeoutMillis = -1;
}
// 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 {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
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;
}
}
从Looper.loop()方法调用MessageQueue.next()方法时的注释可得知,该方法是一个会进入阻塞状态的方法。next()方法中有两个重要的局部变量 – pendingIdleHandlerCount和nextPollTimeoutMillis。pendingIdleHandlerCount表示当前需要处理的Idlehandler的数量,当MessageQueue中没有需要立即处理分发的Messages,就会执行mIdleHandlers中注册的Idlehandler。nextPollTimeoutMillis表示下一次poll等待的时间,这个是epoll_wait的timeout参数,当值为0时,表示立即返回,不进行阻塞;当值为-1时,表示阻塞到有数据;当值大于0时,表示则是nextPollTimeoutMillis个ms时间。
当next()方法刚进入时,nextPollTimeoutMillis为0,调用nativePollOnce()本地方法(实际上是调用到(native层的Looper.pollOnce()方法)。Looper.pollInner()方法比较长,我们精简出我们要的逻辑代码。
int Looper::pollInner(int timeoutMillis) {
// Adjust the timeout based on when the next message is due.
if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
if (messageTimeoutMillis >= 0
&& (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
timeoutMillis = messageTimeoutMillis;
}
}
// Poll.
int result = POLL_WAKE;
// We are about to idle.
mPolling = true;
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// No longer idling.
mPolling = false;
// Acquire lock.
mLock.lock();
// Handle all events.
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeEventFd.get()) {
if (epollEvents & EPOLLIN) {
awoken();
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
}
}
}
Done: ;
// Release lock.
mLock.unlock();
return result;
}
从Looper.pollInner()方法中提取出以上跟消息的分析有关的逻辑代码。
正常情况下,timeoutMillis为传入参数的值,这个变量的值被传入到epoll_wait中。第一次传入的值为0,表示epoll_wait不会进行阻塞等待数据,只会检查一下是否有数据,会出现两种情况:
1.此时没有数据,eventCount = 0,直接返回。
2.此时有数据,且是mWakeEventFd的数据,则调用awoken()方法。
第二种情况使用于后面阻塞的场景,因此在后面分析。按照第一种情况,nativePollOnce()方法直接返回,我们继续回到next()方法分析。
当nativePollOnce()返回后,next()方法就会去比较当前的时间与Messages链表头的Message的时间戳,如果当前时间已经到了头Message的时间戳,则表明是时候处理这个消息了,处理好链表的删除操作后,将这个Message返回,已供Looper去分发处理。当时间还没到最近一个Message的处理时间,则计算需要等待的时间(如果当前Messages链表中没有消息,则为-1)。
此时next()方法并不是直接进入nativePollOnce()方法去等待,而是去查看一下是否有pending的Idlehandlers需要去处理,Idlehandlers顾名思义,就是在MessageQueue空闲的时候进行处理的事务,当当前没有需要立即处理的消息(Messages链表为null或者当前的Message处理的时间还没到),此时才会去进行处理。而且我们可以看到pendingIdleHandlerCount这个值只有在next()方法的第一次循环时才会小于0.
假设此时MessageQueue空闲,且处理完IdleHandler的事务后,next()方法会再次进行循环,但此时nextPollTimeoutMillis的值会被重新清零,因为此时有可能最近的一次Message已经到时间去处理了。
当nextPollTimeoutMillis的值为非零值时,我们再回到native层的Looper.pollInner()方法中,此时epoll_wait则将会等待超时来处理下一个Message,或者被一个新的更优先处理的Message进来打断去处理(enqueueMessage()方法的分析种有说明)。第一种情况则直接返回,第二种情况则会调用native层的Looper.awoken()方法去清除掉mWakeEventFd的内容。
被打断的情况有可能时立即需要处理的Message,此种情况则立即将该Message返回到Java层的Looper.loop()方法。如果是并非立即处理的Message,则会重新计算nextPollTimeoutMillis的值,再次进入到阻塞状态。
经过Java层的Looper.loop()方法和MessageQueue.next()方法的配合,Message的分发处理就是这样不断地流转。
消息的remove
消息的remove只是一个概括,从前面的Handler和MessageQueue的类图中可以看到有一些对Message的处理 – 判断队列(链表)中是否有什么类型的Messages(hasMessages)和删除一个类型的Messages(removeMessages、removeCallbacksAndMessages等)。甚至包括enqueueMessage,其实都是对单链表的常用操作。我们这里就不再展开分析。
MessageQueue中的IdleHandler
我们在MessageQueue.next()方法中可以看到IdleHandler的使用,但我们还没有以具体的例子来进行分析其作用,因此在这一节中使用ActivityThread的源码来进行分析:
2040: private class Idler implements MessageQueue.IdleHandler {
2079: final class GcIdler implements MessageQueue.IdleHandler {
2088: final class PurgeIdler implements MessageQueue.IdleHandler {
以AndroidQ版本的源码来看,ActivityThread中有三个实现继承了MessageQueue.IdleHandler。我们本节不展开说明这三个IdleHandler的具体作用,只看与MessageQueue相关的操作,我们找比较简单的GcIdle来进行简单分析:
final class GcIdler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
doGcIfNeeded();
purgePendingResources();
return false;
}
}
final GcIdler mGcIdler = new GcIdler();
void scheduleGcIdler() {
if (!mGcIdlerScheduled) {
mGcIdlerScheduled = true;
Looper.myQueue().addIdleHandler(mGcIdler);
}
mH.removeMessages(H.GC_WHEN_IDLE);
}
void unscheduleGcIdler() {
if (mGcIdlerScheduled) {
mGcIdlerScheduled = false;
Looper.myQueue().removeIdleHandler(mGcIdler);
}
mH.removeMessages(H.GC_WHEN_IDLE);
}
在ActivityThread的代码中与GcIdler相关的代码只有上面几行,我们可以看到使用MessageQueue.IdleHandler的步骤主要有下面3步:
1.实现MessageQueue.IdleHandler,重写queueIdle()方法,以实现自己想要的功能。queueIdle()的返回值表示这个Handler是否在被执行后继续保存在MessageQueue中,true表示可不断被执行,false表示只执行一次。
2.在适当的时机将这个IdleHandler实例注册到MessageQueue中,调用MessageQueue.addIdleHandler()方法注册。
3.在适当的时机将这个IdleHandler实例从MessageQueue中注销,调用MessageQueue,removeIdleHandler()方法注销。
设计特点
MessageQueue的核心在这里有两个核心点 : 使用单链表的数据结构管理Message以及使用native层的epoll机制(native层Looper)。这两者的相互配合,使得Message机制得以运行。
native层Looper
MessageQueue.addOnFileDescriptorEventListener
MessageQueue还提供了监听文件节点的功能,我们这一章主要分析一下这个功能的实现方式及其作用,结合NetworkStack的应用场景来看看是怎么使用这个功能的。
在NetworkStack的源码中搜索addOnFileDescriptorEventListener,可以找到只有一处在使用:
// packages/modules/NetworkStack/src/android/net/util/FdEventsReader.java
private void createAndRegisterFd() {
if (mFd != null) return;
try {
mFd = createFd();
} catch (Exception e) {
logError("Failed to create socket: ", e);
closeFd(mFd);
mFd = null;
}
if (mFd == null) return;
mQueue.addOnFileDescriptorEventListener(
mFd,
FD_EVENTS,
(fd, events) -> {
// Always call handleInput() so read/recvfrom are given
// a proper chance to encounter a meaningful errno and
// perhaps log a useful error message.
if (!isRunning() || !handleInput()) {
unregisterAndDestroyFd();
return UNREGISTER_THIS_FD;
}
return FD_EVENTS;
});
onStart();
}
FdEventsReader是一个抽象类,createFd是一个抽象方法,在这里主要是有两个重点:①调用createFd创建一个文件节点,这个文件节点肯定是一个类似与pipe之类的多端文件通道。②调用MessageQueue.addOnFileDescriptorEventListener注册文件监听器,实现OnFileDescriptorEventListener接口类的onFileDescriptorEvents()方法,这里使用的是lamda表达式。
FdEventsReader有两个实现类,我们以其中一个来看:
// packages/modules/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
@Override
protected FileDescriptor createFd() {
FileDescriptor fd = null;
try {
fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE);
Os.bind(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH));
NetlinkSocket.connectToKernel(fd);
if (VDBG) {
final SocketAddress nlAddr = Os.getsockname(fd);
Log.d(TAG, "bound to sockaddr_nl{" + nlAddr.toString() + "}");
}
} catch (ErrnoException|SocketException e) {
logError("Failed to create rtnetlink socket", e);
NetworkStackUtils.closeSocketQuietly(fd);
return null;
}
return fd;
}
createFd()方法创建了一个socket,socket大部分人都使用过,这里创建的是Netlink的socket,然后将这个socket fd返回。
我们再看会MessageQueue的addOnFileDescriptorEventListener()方法。
public void addOnFileDescriptorEventListener(@NonNull FileDescriptor fd,
@OnFileDescriptorEventListener.Events int events,
@NonNull OnFileDescriptorEventListener listener) {
synchronized (this) {
updateOnFileDescriptorEventListenerLocked(fd, events, listener);
}
}
private void updateOnFileDescriptorEventListenerLocked(FileDescriptor fd, int events,
OnFileDescriptorEventListener listener) {
final int fdNum = fd.getInt$();
int index = -1;
FileDescriptorRecord record = null;
if (mFileDescriptorRecords != null) {
index = mFileDescriptorRecords.indexOfKey(fdNum);
if (index >= 0) {
record = mFileDescriptorRecords.valueAt(index);
if (record != null && record.mEvents == events) {
return;
}
}
}
if (events != 0) {
events |= OnFileDescriptorEventListener.EVENT_ERROR;
if (record == null) {
if (mFileDescriptorRecords == null) {
mFileDescriptorRecords = new SparseArray<FileDescriptorRecord>();
}
record = new FileDescriptorRecord(fd, events, listener);
mFileDescriptorRecords.put(fdNum, record);
} else {
record.mListener = listener;
record.mEvents = events;
record.mSeq += 1;
}
nativeSetFileDescriptorEvents(mPtr, fdNum, events);
} else if (record != null) {
record.mEvents = 0;
mFileDescriptorRecords.removeAt(index);
nativeSetFileDescriptorEvents(mPtr, fdNum, 0);
}
}
updateOnFileDescriptorEventListenerLocked()方法有三个传参:①文件描述符fd;②所要监听的事件类型;③监听回调OnFileDescriptorEventListener接口类实现。同时updateOnFileDescriptorEventListenerLocked也是removeOnFileDescriptorEventListener()所调用的方法,add和remove的区别就是监听事件类型,只要监听的事件类型不为0,则表示注册监听事件,为0表示注销监听。
事件的类型分为三类:EVENT_INPUT(输入事件,可读取状态);EVENT_OUTPUT(输出事件,写入状态);EVENT_ERROR(异常状态)。
updateOnFileDescriptorEventListenerLocked的实现比较简单,主要是根据注册/注销操作对mFileDescriptorRecords(内部实现就是两个数组保存keys和values,keys为int类型数据,然后根据keys的索引来找到value)进行管理。然后调用nativeSetFileDescriptorEvents去更新native层的数据:
void NativeMessageQueue::setFileDescriptorEvents(int fd, int events) {
if (events) {
int looperEvents = 0;
if (events & CALLBACK_EVENT_INPUT) {
looperEvents |= Looper::EVENT_INPUT;
}
if (events & CALLBACK_EVENT_OUTPUT) {
looperEvents |= Looper::EVENT_OUTPUT;
}
mLooper->addFd(fd, Looper::POLL_CALLBACK, looperEvents, this,
reinterpret_cast<void*>(events));
} else {
mLooper->removeFd(fd);
}
}
MessageQueue中的文件节点的监听实际上使用的是native层Looper监听文件节点的方式,这个是InputFlinger中InputDispatcher的实现类似,我们这里也步展开分析,只看一下native层Looper除了在Message机制中的作用外监听文件节点的功能。
Looper.addFd和Looper.removeFd
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : nullptr, data);
}
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
if (!callback.get()) {
if (! mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return -1;
}
if (ident < 0) {
ALOGE("Invalid attempt to set NULL callback with ident < 0.");
return -1;
}
} else {
ident = POLL_CALLBACK;
}
{ // acquire lock
AutoMutex _l(mLock);
Request request;
request.fd = fd;
request.ident = ident;
request.events = events;
request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;
if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
struct epoll_event eventItem;
request.initEventItem(&eventItem);
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno));
return -1;
}
mRequests.add(fd, request);
} else {
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_MOD, fd, &eventItem);
if (epollResult < 0) {
if (errno == ENOENT) {
epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
if (epollResult < 0) {
ALOGE("Error modifying or adding epoll events for fd %d: %s",
fd, strerror(errno));
return -1;
}
scheduleEpollRebuildLocked();
} else {
ALOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno));
return -1;
}
}
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return 1;
}
addFd和removeFd的代码其实很简单,addFd主要是是将文件描述符fd和NativeMessageQueue实例绑定成Request结构,加入到Looper.mRequests数组中,并将fd添加到epoll的监听队列中去。removeFd则是相反的操作。
Looper.pollInner
我们又回到Looper.pollInner()方法,在这里,epoll_wait监听这我们所注册进来的fd,以下是我们提取出跟Request相关的代码:
int Looper::pollInner(int timeoutMillis) {
// Poll.
int result = POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;
// We are about to idle.
mPolling = true;
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// No longer idling.
mPolling = false;
// Acquire lock.
mLock.lock();
// Rebuild epoll set if needed.
if (mEpollRebuildRequired) {
mEpollRebuildRequired = false;
rebuildEpollLocked();
goto Done;
}
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeEventFd.get()) {
} else {
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
pushResponse(events, mRequests.valueAt(requestIndex));
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
Done: ;
// Release lock.
mLock.unlock();
// Invoke all response callbacks.
for (size_t i = 0; i < mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident == POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
int callbackResult = response.request.callback->handleEvent(fd, events, data);
if (callbackResult == 0) {
removeFd(fd, response.request.seq);
}
response.request.callback.clear();
result = POLL_CALLBACK;
}
}
return result;
}
当监听到注册的fd发生事件,则先将这些事件封装成Respone数据,然后在pollInner的结束时去调用callback(NativeMessageQueue)的handleEvent方法回调,如果handleEvent的返回值为0,则注销这个监听。
MessageQueue.dispatchEvents
int NativeMessageQueue::handleEvent(int fd, int looperEvents, void* data) {
int events = 0;
if (looperEvents & Looper::EVENT_INPUT) {
events |= CALLBACK_EVENT_INPUT;
}
if (looperEvents & Looper::EVENT_OUTPUT) {
events |= CALLBACK_EVENT_OUTPUT;
}
if (looperEvents & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP | Looper::EVENT_INVALID)) {
events |= CALLBACK_EVENT_ERROR;
}
int oldWatchedEvents = reinterpret_cast<intptr_t>(data);
int newWatchedEvents = mPollEnv->CallIntMethod(mPollObj,
gMessageQueueClassInfo.dispatchEvents, fd, events);
if (!newWatchedEvents) {
return 0; // unregister the fd
}
if (newWatchedEvents != oldWatchedEvents) {
setFileDescriptorEvents(fd, newWatchedEvents);
}
return 1;
}
NativeMessageQueue.handleEvent()方法将Looper传过来的事件类型转换成MessageQueue这边的events,并调用Java层MessageQueue的dispatchEvents()方法来回调用户注册的回调方法,并根据其返回的继续监听的事件类型来进行判断,如果新的监听事件为0,表示不需要继续监听,则将这个监听注销,返回0。如果新的监听事件与旧的监听事件不同,则更新监听事件。
// Called from native code.
@UnsupportedAppUsage
private int dispatchEvents(int fd, int events) {
// Get the file descriptor record and any state that might change.
final FileDescriptorRecord record;
final int oldWatchedEvents;
final OnFileDescriptorEventListener listener;
final int seq;
synchronized (this) {
record = mFileDescriptorRecords.get(fd);
if (record == null) {
return 0; // spurious, no listener registered
}
oldWatchedEvents = record.mEvents;
events &= oldWatchedEvents; // filter events based on current watched set
if (events == 0) {
return oldWatchedEvents; // spurious, watched events changed
}
listener = record.mListener;
seq = record.mSeq;
}
// Invoke the listener outside of the lock.
int newWatchedEvents = listener.onFileDescriptorEvents(
record.mDescriptor, events);
if (newWatchedEvents != 0) {
newWatchedEvents |= OnFileDescriptorEventListener.EVENT_ERROR;
}
// Update the file descriptor record if the listener changed the set of
// events to watch and the listener itself hasn't been updated since.
if (newWatchedEvents != oldWatchedEvents) {
synchronized (this) {
int index = mFileDescriptorRecords.indexOfKey(fd);
if (index >= 0 && mFileDescriptorRecords.valueAt(index) == record
&& record.mSeq == seq) {
record.mEvents = newWatchedEvents;
if (newWatchedEvents == 0) {
mFileDescriptorRecords.removeAt(index);
}
}
}
}
// Return the new set of events to watch for native code to take care of.
return newWatchedEvents;
}
MessageQueue.dispatchEvents的核心就是根据fd找到对应的listener对象,调用其onFileDescriptorEvents()方法去处理这个事件,并根据其返回的继续需要监听的事件做与NativeMessageQueue.handleEvent类似的操作。回顾NetworkStack的FdEventsReader的addOnFileDescriptorEventListener的代码,可以知道,其主要作用就是利用Android的native层的Looper来实现对Linux内核的netlink socket的监听。类似的还有InputFlinger的InputDispatcher的对应用的InputChannel的回调监听。
总结
以上是Android Message机制个人理解的框图,总结如下:
1.每个线程Thread最多只有一个Looper和MessageQueue实例,一个进程可以有多个Looper和MessageQueue实例,可以参考SystemServer。
2.每个Looper和MessageQueue实例是一一对应的,Looper是线程的主体,线程的最终执行代码将是Looper的不断循环执行,MessageQueue是消息的容器,也是Looper种不断执行的指令来源。
3.MessageQueue中的重要数据元素就是Message,MessageQueue中组织Message的容器使用的是单链表。链表中Message在入链表时会进行排序,其排序时根据处理时间的顺序,也就是说链表头的Message会最先被处理。
4.Message和Handler的实例在一个线程中并不是唯一的,但两种是互相绑定的,Message中必然会有一个与其相关的Handler实例,这个Handler实例是分发Message的中介,同时也可以是Message的处理句柄,用于处理Message。但Message并不一定要交由Handler来处理,Message可以设置自己的Callback(Runnable),执行Runnable的内容。
5.Message是实现使用了缓存池的机制,主要是为了减少Java层创建对象的开销。Message是Android java层常用的类型,一个进程运行的过程可能会使用非常多的Message,如果每个Message都重新创建,会加大cpu的开销(创建需要消耗cpu,同样的,销毁执行gc也是需要消耗cpu的)。
6.MessageQueue.next()方法是一个阻塞的方法,Looper.loop()方法就是通过阻塞来进入休眠,而这个阻塞是MessageQueue的JNI层调用native层Looper实现的,native层Looper使用的是epoll机制进行监听和阻塞。
问题
1.在知乎上看到有人问,Android 中为什么需要Handler?
我认为Handler的说法并不准确,应该说的是Android为什么需要Message机制,Handler只是Message机制中的处理方式,或者说是处理消息的一种手段的具体实现,而实际上核心的东西是整套机制的协调使用。
Android中为什么需要Message机制呢?我认为主要是因为Android的设计框架很多都是基于C/S结构的,进程间、进程内线程间,很多都可以看作是C/S的架构,如SystemServer、AndroidO之后的hal层服务以及应用的UI刷新,这些都可以看作是C/S架构。那么Android中进程间的C/S架构的通信机制设计有了Binder(HwBinder等),那么线程间的通信机制呢?因为线程间是处于同一个资源集合中,无需使用Binder这种经过内核态的通信机制,而消息机制就很适合这种场景,其有控制简单,串行(消息都是通过一个线程处理)的特点,十分适合线程间通信的。
知乎上有人就Android应用的场景展开说明,谈到UI更新的使用,看似十分有理,但这仅仅只是Message机制的一个应用场景,从源码上看,一个进程并不是只能有一个Looper的存在,而是可以有多个Looper的,UI线程都是在主线程种,但是Looper并不需要一定在主线程种,而且较为新的版本种,Message机制并不仅仅可以作为消息传递,还能监听一个文件节点(socket,驱动节点等),站在系统的层面上看,Android系统是一个集中处理数据的大型软件,数据的处理离不开消息的驱动,那么必然需要一种消息机制来进行驱动,消息的机制驱动又可以分别进程间和线程间的。进程间已有binder这一高效的通信机制,那么线程间也必然需要设计一款高效的通信机制,Message机制也就应运而生(其实很多系统都会有类似的机制)。
2.MessageQueue.next()方法中,调用nativePollOnce()的作用是什么?特别是第一次循环时的作用。
nativePollOnce是进入线程阻塞的核心方法,其底层是基于epoll机制。但第一次循环时epoll的timeout为0,表示进行阻塞,只读取事件,我认为作用用二:①清除过时的wake事件;②处理监听的文件节点事件。