android消息机制原理
在android框架或者应用程序开发中,随处可见Handler类和Looper类的使用,对应用程序而言,它的主类,也就是入口,是框架层的ActivityThread.java 类,当应用程序被启动之后就会进入ActivityThread的main方法
public static void main(String[] args) {
....
Looper.prepareMainLooper();//创建消息队列
ActivityThread thread = new ActivityThread();
thread.attach(false);
....
Looper.loop();//创建消息循环
}
}
SystemServer进程和所有的应用程序进程都是通过消息来驱动,系统为每个用用程序和SystemServer进程维护一个消息队列和消息循环,而应用程序和SystemServer进程的主线程通过循环不断的从这消息队列中获取消息,然后对获取的消息就行处理,这样就实现了通过消息来驱动应用程序和SystemServer进程的执行,这就是android消息处理机制,android消息机制由四个重要的类组成,分别是消息Message,消息队列MessageQueue,消息循环Looper,消息的发送和处理者Handler。
在消息处理机制中,消息都存放在一个消息队列中,应用程序和SystemServer进程的主线程围绕着这个消息队列进入一个无限循环,直到应用程序和SystemServer进程退出。当应用程序和SystemServer进程的Handler向消息队列发送了一个消息之后,消息队列中就有消息了,这个时候应用程序和SystemServer进程的主线程会把这个消息取出来,并分发给相应的handler进行处理,如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来,因此,android系统消息机制的核心是
1.创建消息队列,之后进入无限循环读取消息
2.发送消息
3.处理消息,当发送消息之后,无限循环读到这个消息,之后就分给相应的处理者来处理
创建消息队列和进入消息循环
该过程的序列图:
Created with Raphaël 2.1.2
ActivityThread main()
ActivityThread main()
Looper
Looper
MessageQueue
MessageQueue
android_os_MessageQueue
android_os_MessageQueue
Looper.cpp
Looper.cpp
prepareMainLooper
new MessageQueue
nativeInit
nativeInit
new NativeMessageQueue()
new Looper(false)
rebuildEpollLocked
loop
next
android_os_MessageQueue_nativePollOnce
pollOnce
pollOnce
pollInner
awoken()
下面从code的角度开始分析这个流程:
public static void main(String[] args) {
....
Looper.prepareMainLooper();//创建消息队列
ActivityThread thread = new ActivityThread();
thread.attach(false);
....
Looper.loop();//创建消息循环
}
}
ActivityThread的main()方法首先创建一个ActivityThread的实例,然后创建一个消息队列,和消息循环,接下来分析Looper.prepareMainLooper()消息队列和 Looper.loop()消息循环
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
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));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper类中的变量mQueue 是一个消息队列,所有的消息都放在这个队列中,变量sThreadLocal表示目前线程,即应用程序的主线程。
当创建Looper对象的时候调用它的构造方法来创建一个消息队列MessageQueue,并赋值给Looper的mQueue ,创建MessageQueue就会进入MessageQueue的构造方法,
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
在MessageQueue的构造方法中,调用了nativeInit方法,而这个方法是一个native方法,接下来就看这个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);
}
这个方法里面new关键字又创建了一个NativeMessageQueue队列,接下来看一下NativeMessageQueue类的构造方法
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
NativeMessageQueue的构造方法中,创建了一个native的Looper对象,它与java层的Looper不一样,但是他们是一一对应的。通过看Looper代码,发现android消息机制的核心就在native的Looper中,
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
mWakeEventFd = eventfd(0, EFD_NONBLOCK);
LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd. errno=%d", errno);
AutoMutex _l(mLock);
rebuildEpollLocked();
}
looper的构造方法中首先调用eventfd函数创建一个文件描述符mWakeEventFd ,这个文件描述符被用户当做一个事件的等待/响应机制,靠内核去响应用户事件,而参数EFD_NONBLOCK类似于O_NONBLOCK标志,用来设置文件描述符,主要是为了节省对fcntl的额外调用,最后,Looper的构造函数调用rebuildEpollLocked函数来进一步处理:
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
mWakeEventFd = eventfd(0, EFD_NONBLOCK);
LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd. errno=%d", errno);
AutoMutex _l(mLock);
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
// Allocate the new epoll instance and register the wake pipe.
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
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 = mWakeEventFd;
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance. errno=%d",
errno);
}
这个方法是android消息机制的核心所在,
eppol机制:它是一种I/O多路复用技术,是select/poll的加强版,使用epoll会涉及到epoll_create(),epoll_ctl().epoll_wait()这三个重要的函数
epoll_create:创建epoll文件描述符
epoll_ctl:设置监控文件描述符
epoll_wait:等待监控文件描述符发生IO事件
mEpollFd 表示这个文件描述符上最多可以监控8文件描述符接着调用epoll_ctl()函数来告诉epoll监控mEpollFd 文件描述符的什么事件,在这里就是监控mWakeEventFd文件描述符的EPOLL_CTL_ADD事件,当mWakeEventFd有事件触发的时候,就会唤醒正在等待的线程
接下来看一下消息循环loop()
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);
}
当没有消息的时候就return回去,当有消息的时候就获得这个消息,并调用msg的target对象的dispatchMessage方法处理消息,target是一个handler对象,它的值就是应用程序中用来send message的Handler而对象,
Message next() {
...
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
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;
....
循环中nativePollOnce是一个native方法,它查看当前消息队列中是否有消息,如果有消息就获得,如果没有消息就等待,
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);
}
android_os_MessageQueue_nativePollOnce方法调用native的nativeMessageQueue对象的pollOnce方法进一步处理,pollOnce()方法中有这一句代码mLooper->pollOnce(timeoutMillis);然后由looper中的pollOnce,然后调用了 pollInner(timeoutMillis)继续处理
int Looper::pollInner(int timeoutMillis) {
....
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
...
// 说明发生了错误
if (eventCount < 0) {
if (errno == EINTR) {
goto Done;
}
ALOGW("Poll failed with an unexpected error, errno=%d", errno);
result = POLL_ERROR;
goto Done;
}
//说明超时了
if (eventCount == 0) {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - timeout", this);
#endif
result = POLL_TIMEOUT;
goto Done;
}
...
for (int i = 0; i < eventCount; i++) {//说明有事件发生
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeEventFd) {
if (epollEvents & EPOLLIN) {
awoken();//读取事件
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
}
} 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);
}
}
当eventCount大于0的时候,说明有时间发生,调用awoken()读取事件
void Looper::awoken() {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ awoken", this);
#endif
uint64_t counter;
TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
}
awoken() 函数通过read函数读出这个事件,这个事件在应用程序发送消息的时候写进。