2月份写的文章.发上来.
Android的消息处理机制由三部分组成:消息循环、消息发送、消息处理。
消息循环
消息都存在在一个消息队列中,应用程序的主线程会不断读取其中的消息,并分派给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就进入空闲等待状态。
消息循环通过Looper类来实现。
这里分两部分
一.Looper.prepareMainLooper
二.Looper.loop
Looper.prepareMainLooper
public final class Looper {
……
//sThreadLocal.get() will return null unless you've called prepare().
static finalThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private staticLooper sMainLooper; // guarded byLooper.class
finalMessageQueue mQueue;
……
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
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 perthread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw newIllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
……
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static Looper myLooper() {
return sThreadLocal.get();
}
……
/**
* Return the {@link MessageQueue} object associated with the current
* thread. This must be calledfrom a thread running a Looper, or a
* NullPointerException will be thrown.
*/
public static MessageQueue myQueue() {
return myLooper().mQueue;
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
……
}
prepareMainLooper主要做的事情就是:创建了一个Looper对象,保存在sThreadLocal中,并将这个Looper对象赋值给sMainLooper保存起来。
new Looper:在创建的时候,同时实例化一个MessageQueue。并赋值给mQueue保存起来。后续的消息就通过它来管理。
接下来,我们来看MessageQueue.java
------ frameworks/base/core/java/android/os/MessageQueue.java
public final class MessageQueue {
……
private native static int nativeInit();
private native static void nativeDestroy(int ptr);
private native static void nativePollOnce(int ptr, int timeoutMillis);
private native static void nativeWake(int ptr);
private nativestatic boolean nativeIsIdling(int ptr);
……
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
……
}
可以看出。MessageQueue的整体实现都交给了native.
继续跟,grep一把就可以找到MessageQueue的native实现。
frameworks/base/core/java/android/os/MessageQueue.java
从nativeInit开始
static jintandroid_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate nativequeue");
return 0;
}
nativeMessageQueue->incStrong(env);
return reinterpret_cast<jint>(nativeMessageQueue);
}
可以看出,android_os_MessageQueue_nativeInit在native中创建了一个nativeMessageQueue.
在这个文件中可以找到如下
NativeMessageQueue::NativeMessageQueue(): mInCallback(false), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
nativeMessageQueue在native层又实例化了一个Looper。
Looper.cpp实现在system/core/libutils/Looper.cpp
Looper::Looper(boolallowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks),mSendingMessage(false),
mResponseIndex(0),mNextMessageUptime(LLONG_MAX) {
int wakeFds[2];
int result = pipe(wakeFds);
LOG_ALWAYS_FATAL_IF(result != 0,"Could not create wake pipe. errno=%d", errno);
mWakeReadPipeFd =wakeFds[0];
mWakeWritePipeFd =wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL,O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0,"Could not make wake read pipe non-blocking. errno=%d", errno);
result = fcntl(mWakeWritePipeFd, F_SETFL,O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0,"Could not make wake write pipe non-blocking. errno=%d", errno);
mIdling = false;
// Allocate the epoll instance and registerthe wake pipe.
mEpollFd =epoll_create(EPOLL_SIZE_HINT);//#------ EPOLL_SIZE_HINT是在这个mEpollFd上能监控的最大文件描述符数,这里创建了epoll的filedescription
LOG_ALWAYS_FATAL_IF(mEpollFd < 0,"Could not create epoll instance. errno=%d", 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 = mWakeReadPipeFd;//#------将mWakeReadPipeFd赋值进去,就是说有内容更新,就立马wake线程去读取。
result = epoll_ctl(mEpollFd,EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
LOG_ALWAYS_FATAL_IF(result != 0,"Could not add wake read pipe to epoll instance. errno=%d", errno);
}
注意看代码中标红部分。
消息的循环使用的是Pipe机制,是linux系统中进程间通信的一种机制。
好像linux进程间的通信总是通过一个文件进行。mWakeReadPipeFd,mWakeWritePipeFd 是pipe的文件描述(FileDescription)。
这是一个多线程机制。
线程A使用FileDescription来读pipe的内容
线程B使用FileDescription来写pipe的内容
Pipe中没内容就线程A就进入wait状态,线程B在进行写操作的时候,就会wake线程A。
Epoll这部分不详。直接应用罗大牛的说明
这个等待和唤醒的操作是如何进行的呢,这就要借助Linux系统中的epoll机制了。 Linux