点击app图标,会进入先创建Application进程然后再启动application的ActivityThread的main方法入口
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
从上面的代码可以看出,最主要是创建Looper并启动循环,我们来看下Looper.java的loop()函数
public static void loop() {
final Looper me = myLooper();
...
for (;;) {
Message msg = queue.next(); // might block
...
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);
}
}
...
msg.recycleUnchecked();
}
}
我们可以看到这里的for循环是个死循环,但为什么不会卡死程序了。
从MessageQueue取Message时调用了queue.next()函数,
在MessageQueue.java的next()函数的代码如下
@UnsupportedAppUsage
Message next() {
...
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
...
}
}
我们看到了最重要的函数,nativePollOnce,这是一个native的函数,也就是一个用c++写的函数。
MessageQueue.java里有三个非常重要的native函数
private native static long nativeInit();//MessageQueue初始化时调用,返回的long其实是MessageQueue的操作句柄
private native void nativePollOnce(long ptr, int timeoutMillis);//取消息时用
private native static void nativeWake(long ptr);//唤醒消息队列时使用
我们重要来看下nativePollOnce()方法
frameworks/base/core/jni/android_os_MessageQueue.cpp
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);
}
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->wake();
}
我们在AndroidRuntime.cpp里能找到MessageQueue的JNI注册地方
点击进入到android_os_MessageQueue.cpp文件里,可以看到MessageQueue.java里的6个native方法
我们来看下nativePollOnce()方法
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
mLooper->pollOnce(timeoutMillis);
mPollObj = NULL;
mPollEnv = NULL;
if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
void NativeMessageQueue::wake() {
mLooper->wake();
}
可认看到NativeMessageQueue::pollOnce方法调用到了Looper.pollOnce,而此时的Looper是
system/core/libutils/Looper.cpp
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
// 创建事件句柄mWakeEventFd,用于唤醒
mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
// 创建epoll句柄
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
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;
// 把mWakeEventFd加入epoll监听,监听写入(EPOLLIN)事件
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
}
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
... ...
result = pollInner(timeoutMillis);
}
}
int Looper::pollInner(int timeoutMillis) {
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
// 等待监听事件
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
... ...
return result;
}
void Looper::wake() {
uint64_t inc = 1;
// 向mWakeEventFd写入数据(写入什么数据并不重要),用于唤醒消息队列
// 调用这个方法后epoll_wait函数会返回,沿着调用链一路向上pollInner->pollOnce->pollOnce->android_os_MessageQueue_nativePollOnce->nativePollOnce->next
// 这个时候Looper.loop()调用的next()会返回,循环体继续执行
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
}
这里就是Android系统的handler消息机制的循环核心实现,使用了linux的epoll事件处理机制。当消息队列为空时,常规的循环实现的调用sleep/usleep释放cpu,当时间到了之后,会获取cpu资源进行一次消息检查;Handler消息循环采用Linux 内核的epoll机制,当消息列表为空时,会挂起释放cpu资源 ,只有当消息列表有消息时,才会重新获取cpu资源,进行消息处理。
Android的消息机制的生产者,会把消息放入消息列表的同时,通知唤醒消息处理者(Looper)
下面我们来说说为什么epoll如此高效。