關(guān)于Java層的 Handler仔沿,Looper 都已經(jīng)很清楚了痴鳄。接下想了解一下 Looper 的阻塞柏卤。
Looper 的阻塞主要是靠 MessageQueue 來實現(xiàn)的省容,在next()@MessageQuese 進(jìn)行阻塞抖拴,在 enqueueMessage()@MessageQueue 進(jìn)行喚醒。主要依賴 native 層的 Looper 依靠 epoll 機(jī)制進(jìn)行的腥椒。
//../frameworks/base/core/java/android/os/MessageQueue.java
MessageQueue(boolean quitAllowed){
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
//../frameworks/base/core/jni/android_os_MessageQueue.cpp
//從 nativce 層創(chuàng)建一個 NativeMessageQueue 對象城舞,并且將其句柄返回到 Java 層保存在 mPtr 中
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessaeQueue* nativeMessageQueue = new NativeMessageQueue();
...
return reinterpret_cast<jlong>(nativeMessageQueue);
}
NativeMessageQueue::NativeMessageQueue() : mPollEnv(NULL),mPollObj(NULL), mExceptionPbj(NULL){
//native 層的 Looper 也是 TLS 的
mLooper = Looper::getForThread();
if(mLooper = NULL){
//如果當(dāng)前線程沒有 Looper,實例化并且設(shè)置到 TLS
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
//.././/system/core/libutils/Looper.cpp
Looper::Looper(bool allowNonCallbacks):...{
//返回 mWakeEventFd寞酿,用來喚醒 epoll_wait()
mWakeEventFd = eventfd(0, EFD_NONBLOCK);
...
//創(chuàng)建 epoll 文件描述符,并且mWakeEventFd 加入到 epoll 監(jiān)聽隊列
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked(){
...
//創(chuàng)建一個 epoll 實例
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
...
//將感興趣的文件描述符添加脱柱,即 mWakeEventFd
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem);
...
}
至此伐弹,Java 層的 MessageQueue 就創(chuàng)建好了,來看看 native 層做了什么榨为。native 層實例化了一個 NativeMessageQueue惨好,并且將其句柄返回到 MessageQueue 進(jìn)行保存,同時實例化了 TLS(Thread Local Storage) 相關(guān)的Looper随闺。并且使用 epoll機(jī)制(Linux 相關(guān)日川,不知道原理)。
Message next(){
...
for(;;){
...
//在這里進(jìn)行阻塞
nativePollOnce(ptr, nextPollTimeoutMillis);
//下面是從消息頭取消息矩乐,因為enqueueMessage()是將消息放在隊頭
...
}
}
//android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj){
NativeMessage* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->pollOnce(env,obj,timeoutMillions);
}
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillions){
..
mLooer->pollOnce(timeoutMillis);
...
}
//Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void ** outData){
...
result = pollInner(timeoutMillis);
}
int Looper::pollInner(int timeoutMillis){
...
//就是在這里利用 epoll_wait() 進(jìn)行阻塞等待,這里timeoutMills 表示等待時間
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
...
awaken();
...
}
上面表明了進(jìn)行阻塞的地方龄句,現(xiàn)在來說明進(jìn)行喚醒的地方
//MessageQueue.java
boolean enqueueMessage(Message msg, long when){
...
//將消息放到隊頭
if(needWake){
//就是在這里進(jìn)行喚醒
nativeWake(mPtr);
}
}
//android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr){
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeMessageQueue->wake();
}
void NativeMessageQueue::wake(){
mLooper->wake();
}
void Looper::wake(){
...
//往mWakeEventFd 中write 1回论,用以喚醒 looper
ssize_t mWrite = TEMP_FAILURE_READY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
}
這樣就喚醒了epoll_wait(),然后繼續(xù)方法調(diào)動awoken(),這個方法就是將之前寫入的1讀出分歇,表示消費這個事件
void Looper::awaken(){
...
TEMP_FAILURE_READY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
}
隨后在Java 層的next()@MessageQueue 就被喚醒傀蓉,讀取在enqueueMessage()@MessageQueue 插在隊頭的消息進(jìn)行處理