欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android7.0 MessageQueue詳解

 更新時(shí)間:2016年09月22日 10:15:44   作者:Gaugamela  
這篇文章主要為大家詳細(xì)介紹了Android7.0 MessageQueue的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

Android中的消息處理機(jī)制大量依賴于Handler。每個(gè)Handler都有對(duì)應(yīng)的Looper,用于不斷地從對(duì)應(yīng)的MessageQueue中取出消息處理。

一直以來(lái),覺(jué)得MessageQueue應(yīng)該是Java層的抽象,然而事實(shí)上MessageQueue的主要部分在Native層中。
自己對(duì)MessageQueue在Native層的工作不太熟悉,借此機(jī)會(huì)分析一下。

一、MessageQueue的創(chuàng)建

當(dāng)需要使用Looper時(shí),我們會(huì)調(diào)用Looper的prepare函數(shù):

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為線程本地存儲(chǔ)區(qū);每個(gè)線程僅有一個(gè)Looper
 sThreadLocal.set(new Looper(quitAllowed));
}

private Looper(boolean quitAllowed) {
 //創(chuàng)建出MessageQueue
 mQueue = new MessageQueue(quitAllowed);
 mThread = Thread.currentThread();
}

1 NativeMessageQueue

我們看看MessageQueue的構(gòu)造函數(shù):

MessageQueue(boolean quitAllowed) {
 mQuitAllowed = quitAllowed;
 //mPtr的類型為long?
 mPtr = nativeInit();
}

MessageQueue的構(gòu)造函數(shù)中就調(diào)用了native函數(shù),我們看看android_os_MessageQueue.cpp中的實(shí)現(xiàn):

static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
 //MessageQueue的Native層實(shí)體
 NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
 ............
 //這里應(yīng)該類似與將指針轉(zhuǎn)化成long類型,放在Java層保存;估計(jì)Java層使用時(shí),會(huì)在native層將long變成指針,就可以操作隊(duì)列了
 return reinterpret_cast<jlong>(nativeMessageQueue);
}

我們跟進(jìn)NativeMessageQueue的構(gòu)造函數(shù):

NativeMessageQueue::NativeMessageQueue() :
 mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
 //創(chuàng)建一個(gè)Native層的Looper,也是線程唯一的
 mLooper = Looper::getForThread();
 if (mLooper == NULL) {
 mLooper = new Looper(false);
 Looper::setForThread(mLooper);
 }
}

從代碼來(lái)看,Native層和Java層均有Looper對(duì)象,應(yīng)該都是操作MessageQueue的。MessageQueue在Java層和Native層有各自的存儲(chǔ)結(jié)構(gòu),分別存儲(chǔ)Java層和Native層的消息。

2 Native層的looper

我們看看Native層looper的構(gòu)造函數(shù):

Looper::Looper(bool allowNonCallbacks) :
 mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
 mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
 mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
 //此處創(chuàng)建了個(gè)fd
 mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
 .......
 rebuildEpollLocked();
}

在native層中,MessageQueue中的Looper初始化時(shí),還調(diào)用了rebuildEpollLocked函數(shù),我們跟進(jìn)一下:

void Looper::rebuildEpollLocked() {
 // Close old epoll instance if we have one.
 if (mEpollFd >= 0) {
 close(mEpollFd);
 }

 // Allocate the new epoll instance and register the wake pipe.
 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;
 //在mEpollFd上監(jiān)聽(tīng)mWakeEventFd上是否有數(shù)據(jù)到來(lái)
 int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
 ...........
 for (size_t i = 0; i < mRequests.size(); i++) {
 const Request& request = mRequests.valueAt(i);
 struct epoll_event eventItem;
 request.initEventItem(&eventItem);
 //監(jiān)聽(tīng)request對(duì)應(yīng)fd上數(shù)據(jù)的到來(lái)
 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
 ............
 }
}

從native層的looper來(lái)看,我們知道Native層依賴于epoll來(lái)驅(qū)動(dòng)事件處理。此處我們先保留一下大致的映像,后文詳細(xì)分析。

二、使用MessageQueue

1 寫入消息
 Android中既可以在Java層向MessageQueue寫入消息,也可以在Native層向MessageQueue寫入消息。我們分別看一下對(duì)應(yīng)的操作流程。

1.1 Java層寫入消息
Java層向MessageQueue寫入消息,依賴于enqueueMessage函數(shù):

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) {
  .....
  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;
  //在頭部插入數(shù)據(jù),如果之前MessageQueue是阻塞的,那么現(xiàn)在需要喚醒
  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;
  }
  //不是第一個(gè)異步消息時(shí),needWake置為false
  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;
}

上述代碼比較簡(jiǎn)單,主要就是將新加入的Message按執(zhí)行時(shí)間插入到原有的隊(duì)列中,然后根據(jù)情況調(diào)用nativeAwake函數(shù)。

我們跟進(jìn)一下nativeAwake:

void NativeMessageQueue::wake() {
 mLooper->wake();
}

void Looper::wake() {
 uint64_t inc = 1;
 //就是向mWakeEventFd寫入數(shù)據(jù)
 ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
 .............
}

在native層的looper初始化時(shí),我們提到過(guò)native層的looper將利用epoll來(lái)驅(qū)動(dòng)事件,其中構(gòu)造出的epoll句柄就監(jiān)聽(tīng)了mWakeEventFd。
實(shí)際上從MessageQueue中取出數(shù)據(jù)時(shí),若沒(méi)有數(shù)據(jù)到來(lái),就會(huì)利用epoll進(jìn)行等待;因此當(dāng)Java層寫入消息時(shí),將會(huì)將喚醒處于等待狀態(tài)的MessageQueue。
在后文介紹從MessageQueue中提取消息時(shí),將再次分析這個(gè)問(wèn)題。

1.2 Native層寫入消息
Native層寫入消息,依賴于Native層looper的sendMessage函數(shù):

void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
 sendMessageAtTime(now, handler, message);
}

void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
 const Message& message) {
 size_t i = 0;
 {
 AutoMutex _l(mLock);

 //同樣需要按時(shí)間插入
 size_t messageCount = mMessageEnvelopes.size();
 while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
  i += 1;
 }

 //將message包裝成一個(gè)MessageEnvelope對(duì)象
 MessageEnvelope messageEnvelope(uptime, handler, message);
 mMessageEnvelopes.insertAt(messageEnvelope, i, 1);

 // Optimization: If the Looper is currently sending a message, then we can skip
 // the call to wake() because the next thing the Looper will do after processing
 // messages is to decide when the next wakeup time should be. In fact, it does
 // not even matter whether this code is running on the Looper thread.
 if (mSendingMessage) {
  return;
 }
 }
 // Wake the poll loop only when we enqueue a new message at the head.
 if (i == 0) {
 //若插入在隊(duì)列頭部,同樣利用wake函數(shù)觸發(fā)epoll喚醒
 wake();
 }
}

以上就是向MessageQueue中加入消息的主要流程,接下來(lái)我們看看從MessageQueue中取出消息的流程。

2、提取消息
當(dāng)Java層的Looper對(duì)象調(diào)用loop函數(shù)時(shí),就開(kāi)始使用MessageQueue提取消息了:

public static void loop() {
 final Looper me = myLooper();
 .......
 for (;;) {
 Message msg = queue.next(); // might block
 .......
 try {
  //調(diào)用Message的處理函數(shù)進(jìn)行處理
  msg.target.dispatchMessage(msg);
 }........
 }
}

此處我們看看MessageQueue的next函數(shù):

Message next() {
 //mPtr保存了NativeMessageQueue的指針
 final long ptr = mPtr;
 .......
 int pendingIdleHandlerCount = -1; // -1 only during first iteration
 int nextPollTimeoutMillis = 0;

 for (;;) {
 if (nextPollTimeoutMillis != 0) {
  //會(huì)調(diào)用Native函數(shù),最終調(diào)用IPCThread的talkWithDriver,將數(shù)據(jù)寫入Binder驅(qū)動(dòng)或者讀取一次數(shù)據(jù)
  //不知道在此處進(jìn)行這個(gè)操作的理由?
  Binder.flushPendingCommands();
 }

 //處理native層的數(shù)據(jù),此處會(huì)利用epoll進(jìn)行blocked
 nativePollOnce(ptr, nextPollTimeoutMillis);

 synchronized (this) {
  final long now = SystemClock.uptimeMillis();
  Message prevMsg = null;
  Message msg = mMessages;
  //下面其實(shí)就是找出下一個(gè)異步處理類型的消息;異步處理類型的消息,才含有對(duì)應(yīng)的執(zhí)行函數(shù)
  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;
   //完成next記錄的存儲(chǔ)
   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;
  }

  // Process the quit message now that all pending messages have been handled.
  if (mQuitting) {
  dispose();
  return null;
  }

  //MessageQueue中引入了IdleHandler接口,即當(dāng)MessageQueue沒(méi)有數(shù)據(jù)處理時(shí),調(diào)用IdleHandler進(jìn)行一些工作

  //pendingIdleHandlerCount表示待處理的IdleHandler,初始為-1
  if (pendingIdleHandlerCount < 0
   && (mMessages == null || now < mMessages.when)) {
  //mIdleHandlers的size默認(rèn)為0,調(diào)用接口addIdleHandler才能增加
  pendingIdleHandlerCount = mIdleHandlers.size();
  }

  if (pendingIdleHandlerCount <= 0) {
  // No idle handlers to run. Loop and wait some more.
  mBlocked = true;
  continue;
  }

  //將待處理的IdleHandler加入到PendingIdleHandlers中
  if (mPendingIdleHandlers == null) {
  mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
  }
  //調(diào)用ArrayList.toArray(T[])節(jié)省每次分配的開(kāi)銷;畢竟對(duì)于Message.Next這樣調(diào)用頻率較高的函數(shù),能省一點(diǎn)就是一點(diǎn)
  mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
 }

 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 {
  //執(zhí)行實(shí)現(xiàn)類的queueIdle函數(shù),返回值決定是否繼續(xù)保留
  keep = idler.queueIdle();
  } catch (Throwable t) {
  Log.wtf(TAG, "IdleHandler threw exception", t);
  }

  if (!keep) {
  synchronized (this) {
   mIdleHandlers.remove(idler);
  }
  }
 }
 pendingIdleHandlerCount = 0;
 nextPollTimeoutMillis = 0;
 }
}

整個(gè)提取消息的過(guò)程,大致上如上圖所示。
可以看到在Java層,Looper除了要取出MessageQueue的消息外,還會(huì)在隊(duì)列空閑期執(zhí)行IdleHandler定義的函數(shù)。

2.1 nativePollOnce
現(xiàn)在唯一的疑點(diǎn)是nativePollOnce是如何處理Native層數(shù)據(jù)的,我們看看對(duì)應(yīng)的native函數(shù):

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
 jlong ptr, jint timeoutMillis) {
 //果然Java層調(diào)用native層MessageQueue時(shí),將long類型的ptr變?yōu)橹羔?
 NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
 nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}

void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
 mPollEnv = env;
 mPollObj = pollObj;
 //最后還是進(jìn)入到Native層looper的pollOnce函數(shù)
 mLooper->pollOnce(timeoutMillis);
 mPollObj = NULL;
 mPollEnv = NULL;

 if (mExceptionObj) {
 .........
 }
}

看看native層looper的pollOnce函數(shù):

//timeoutMillis為超時(shí)等待時(shí)間。值為-1時(shí),表示無(wú)限等待直到有事件到來(lái);值為0時(shí),表示無(wú)需等待
//outFd此時(shí)為null,含義是:存儲(chǔ)產(chǎn)生事件的文件句柄
//outEvents此時(shí)為null,含義是:存儲(chǔ)outFd上發(fā)生了哪些事件,包括可讀、可寫、錯(cuò)誤和中斷
//outData此時(shí)為null,含義是:存儲(chǔ)上下文數(shù)據(jù),其實(shí)調(diào)用時(shí)傳入的參數(shù)
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
 int result = 0;
 for (;;) {
 //處理response,目前我們先不關(guān)注response的內(nèi)含
 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 != NULL) *outFd = fd;
  if (outEvents != NULL) *outEvents = events;
  if (outData != NULL) *outData = data;
  return ident;
  }
 }

 //根據(jù)pollInner的結(jié)果,進(jìn)行操作
 if (result != 0) {
  if (outFd != NULL) *outFd = 0;
  if (outEvents != NULL) *outEvents = 0;
  if (outData != NULL) *outData = NULL;
  return result;
 }

 //主力還是靠pollInner
 result = pollInner(timeoutMillis);
 }
}

跟進(jìn)一下pollInner函數(shù):

int Looper::pollInner(int timeoutMillis) {
 // Adjust the timeout based on when the next message is due.
 //timeoutMillis是Java層事件等待事件
 //native層維持了native message的等待時(shí)間
 //此處其實(shí)就是選擇最小的等待時(shí)間
 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;
 }
 }

 int result = POLL_WAKE;
 //pollInner初始就清空response
 mResponses.clear();
 mResponseIndex = 0;

 // We are about to idle.
 mPolling = true;

 //利用epoll等待mEpollFd監(jiān)控的句柄上事件到達(dá)
 struct epoll_event eventItems[EPOLL_MAX_EVENTS];
 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

 // No longer idling.
 mPolling = false;

 // Acquire lock.
 mLock.lock();

 //重新調(diào)用rebuildEpollLocked時(shí),將使得epoll句柄能夠監(jiān)聽(tīng)新加入request對(duì)應(yīng)的fd
 if (mEpollRebuildRequired) {
 mEpollRebuildRequired = false;
 rebuildEpollLocked();
 goto Done;
 }

 // Check for poll error.
 if (eventCount < 0) {
 if (errno == EINTR) {
  goto Done;
 }
 ......
 result = POLL_ERROR;
 goto Done;
 }

 // Check for poll timeout.
 if (eventCount == 0) {
 result = POLL_TIMEOUT;
 goto Done;
 }

 for (int i = 0; i < eventCount; i++) {
 if (fd == mWakeEventFd) {
  if (epollEvents & EPOLLIN) {
  //前面已經(jīng)分析過(guò),當(dāng)java層或native層有數(shù)據(jù)寫入隊(duì)列時(shí),將寫mWakeEventFd,以觸發(fā)epoll喚醒
  //awoken將讀取并清空mWakeEventFd上的數(shù)據(jù)
  awoken();
  } else {
  .........
  }
 } else {
  //epoll同樣監(jiān)聽(tīng)的request對(duì)應(yīng)的fd
  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;
  //存儲(chǔ)這個(gè)fd對(duì)應(yīng)的response
  pushResponse(events, mRequests.valueAt(requestIndex));
  } else {
  ..........
  }
 }
 }

Done:

 // Invoke pending message callbacks.
 mNextMessageUptime = LLONG_MAX;
 //處理Native層的Message
 while (mMessageEnvelopes.size() != 0) {
 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
 if (messageEnvelope.uptime <= now) {
  // Remove the envelope from the list.
  // We keep a strong reference to the handler until the call to handleMessage
  // finishes. Then we drop it so that the handler can be deleted *before*
  // we reacquire our lock.
  {
  sp<MessageHandler> handler = messageEnvelope.handler;
  Message message = messageEnvelope.message;
  mMessageEnvelopes.removeAt(0);
  mSendingMessage = true;
  mLock.unlock();

  //處理Native Message
  handler->handleMessage(message);
  }
  mLock.lock();
  mSendingMessage = false;
  result = POLL_CALLBACK;
 } else {
  // The last message left at the head of the queue determines the next wakeup time.
  mNextMessageUptime = messageEnvelope.uptime;
  break;
 }
 }

 // Release lock.
 mLock.unlock();

 //處理帶回調(diào)函數(shù)的response
 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;

  //調(diào)用response的callback
  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;
}

說(shuō)實(shí)話native層的代碼寫的很亂,該函數(shù)的功能比較多。
如上圖所示,在nativePollOnce中利用epoll監(jiān)聽(tīng)是否有數(shù)據(jù)到來(lái),然后處理native message、native response。

最后,我們看看如何在native層中加入request。

3 添加監(jiān)控請(qǐng)求
native層增加request依賴于looper的接口addFd:

//fd表示需要監(jiān)聽(tīng)的句柄
//ident的含義還沒(méi)有搞明白
//events表示需要監(jiān)聽(tīng)的事件,例如EVENT_INPUT、EVENT_OUTPUT、EVENT_ERROR和EVENT_HANGUP中的一個(gè)或多個(gè)
//callback為事件發(fā)生后的回調(diào)函數(shù)
//data為回調(diào)函數(shù)對(duì)應(yīng)的參數(shù)
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
 return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
}

結(jié)合上文native層輪詢隊(duì)列的操作,我們大致可以知道:addFd的目的,就是讓native層的looper監(jiān)控新加入的fd上是否有指定事件發(fā)生。
如果發(fā)生了指定的事件,就利用回調(diào)函數(shù)及參數(shù)構(gòu)造對(duì)應(yīng)的response。
native層的looper處理response時(shí),就可以執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)了。

看看實(shí)際的代碼:

int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
 ........
 {
 AutoMutex _l(mLock);

 //利用參數(shù)構(gòu)造一個(gè)request
 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);

 //判斷之前是否已經(jīng)利用該fd構(gòu)造過(guò)Request
 ssize_t requestIndex = mRequests.indexOfKey(fd);
 if (requestIndex < 0) {
  //mEpollFd新增一個(gè)需監(jiān)聽(tīng)fd
  int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
  .......
  mRequests.add(fd, request);
 } else {
  //mEpollFd修改舊的fd對(duì)應(yīng)的監(jiān)聽(tīng)事件
  int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
  if (epollResult < 0) {
  if (errno == ENOENT) {
   // Tolerate ENOENT because it means that an older file descriptor was
   // closed before its callback was unregistered and meanwhile a new
   // file descriptor with the same number has been created and is now
   // being registered for the first time. 
   epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
   .......
  }
  //發(fā)生錯(cuò)誤重新加入時(shí),安排EpollRebuildLocked,將讓epollFd重新添加一次待監(jiān)聽(tīng)的fd
  scheduleEpollRebuildLocked();
  }
  mRequests.replaceValueAt(requestIndex, request);
 }
 }
}

對(duì)加入監(jiān)控請(qǐng)求的處理,在上文介紹pollInner函數(shù)時(shí)已做分析,此處不再贅述。

三、總結(jié)

1、流程總結(jié)


MessageQueue的整個(gè)流程包括了Java部分和Native部分,從圖中可以看出Native層的比重還是很大的。我們結(jié)合上圖回憶一下整個(gè)MessageQueue對(duì)應(yīng)的處理流程:
1、Java層創(chuàng)建Looper對(duì)象時(shí),將會(huì)創(chuàng)建Java層的MessageQueue;Java層的MessageQueue初始化時(shí),將利用Native函數(shù)創(chuàng)建出Native層的MessageQueue。

2、Native層的MessageQueue初始化后,將創(chuàng)建對(duì)應(yīng)的Native Looper對(duì)象。Native對(duì)象初始化時(shí),將創(chuàng)建對(duì)應(yīng)epollFd和WakeEventFd。其中,epollFd將作為epoll的監(jiān)聽(tīng)句柄,初始時(shí)epollFd僅監(jiān)聽(tīng)WakeEventFd。

3、圖中紅色線條為L(zhǎng)ooper從MessageQueue中取消息時(shí),處理邏輯的流向。
3.1、當(dāng)Java層的Looper開(kāi)始循環(huán)時(shí),首先需要通過(guò)JNI函數(shù)調(diào)用Native Looper進(jìn)行pollOnce的操作。

3.2、Native Looper開(kāi)始運(yùn)行后,需要等待epollFd被喚醒。當(dāng)epollFd等待超時(shí)或監(jiān)聽(tīng)的句柄有事件到來(lái),Native Looper就可以開(kāi)始處理事件了。

3.3、在Native層,Native Looper將先處理Native MessageQueue中的消息,再調(diào)用Response對(duì)應(yīng)的回調(diào)函數(shù)。

3.4、本次循環(huán)中,Native層事件處理完畢后,才開(kāi)始處理Java層中MessageQueue的消息。若MessageQueue中沒(méi)有消息需要處理,并且MessageQueue中存在IdleHandler時(shí),將調(diào)用IdleHandler定義的處理函數(shù)。

圖中藍(lán)色部分為對(duì)應(yīng)的函數(shù)調(diào)用:
在Java層:
利用MessageQueue的addIdleHandler,可以為MessageQueue增加IdleHandler;
利用MessageQueue的enqueueMessage,可以向MessageQueue增加消息;必要時(shí)將利用Native函數(shù)向Native層的WakeEventFd寫入消息,以喚醒epollFd。

在Native層:
利用looper:sendMessage,可以為Native MessageQueue增加消息;同樣,要時(shí)將向Native層的WakeEventFd寫入消息,以喚醒epollFd;
利用looper:addFd,可以向Native Looper注冊(cè)監(jiān)聽(tīng)請(qǐng)求,監(jiān)聽(tīng)請(qǐng)求包含需監(jiān)聽(tīng)的fd、監(jiān)聽(tīng)的事件及對(duì)應(yīng)的回調(diào)函數(shù)等,監(jiān)聽(tīng)請(qǐng)求對(duì)應(yīng)的fd將被成為epollFd監(jiān)聽(tīng)的對(duì)象。當(dāng)被監(jiān)聽(tīng)的fd發(fā)生對(duì)應(yīng)的事件后,將會(huì)喚醒epollFd,此時(shí)將生成對(duì)應(yīng)response加入的response List中,等待處理。一旦response被處理,就會(huì)調(diào)用對(duì)應(yīng)的回調(diào)函數(shù)。

2、注意事項(xiàng)
MessageQueue在Java層和Native層有各自的存儲(chǔ)結(jié)構(gòu),可以分別增加消息。從處理邏輯來(lái)看,會(huì)優(yōu)先處理native層的Message,然后處理Native層生成的response,最后才是處理Java層的Message。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論