Android中消息处理机制主要围绕消息队列来实现的。一个线程拥有一个消息队列之后,就可以进入到一个消息循环中,同时其他线程以及线程本身可以往这个消息队列发送消息,以便在这个消息被处理时执行一个特定的操作。
Android系统主要是通过MessageQueue、Looper和Handler三个类实现消息处理机制的。其中MessageQueue来描述消息队列;Looper类用来创建消息队列以及消息循环;Handler用来发送消息和处理消息。
先看一个典型的Looper线程实例
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
从实例中看出我们先调用了Looper.prepare()在其中会创建消息队列,Looper.loop()在其中会进行消息循环的过程。Handler进行消息的发送和处理
一、创建线程消息队列
Android 中消息队列是使用MessageQueue对象来描述的,它是在Looper的构造方法中创建的,可以通过调用looper的静态方法prepareMainLooper和prepare方法来实例化Looper。
frameworks/base/core/java/android/os/Looper.java
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
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.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 new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
}
Looper类有一个类型为ThreadLocal的静态成员变量sThreadLocal,用来保存线程中的Looper对象。在Looper的静态成员函数prepare方法中,if语句会检查当前线程是否已经存在Looper对象,如果存在就会抛出异常;否则就会创建Looper实例并将它保存在Looper的静态成员变量sThreadLocal中。
prepareMainLooper()方法只能有系统调用,用来创建我们应用程序主线程的消息队列。Androidxitpng 是在ActivityThread的静态成员函数main方法中调用的。
一个looper对象在创建过程中,会在构造方法中创建一个MessageQueue对象,并且保存在成员变量mQueue中
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
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 const JNINativeMethod gMessageQueueMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
{ "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },
{ "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce },
{ "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake },
{ "nativeIsPolling", "(J)Z", (void*)android_os_MessageQueue_nativeIsPolling },
{ "nativeSetFileDescriptorEvents", "(JII)V",
(void*)android_os_MessageQueue_nativeSetFileDescriptorEvents },
};
int register_android_os_MessageQueue(JNIEnv* env) {
int res = RegisterMethodsOrDie(env, "android/os/MessageQueue", gMessageQueueMethods,
NELEM(gMessageQueueMethods));
jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");
gMessageQueueClassInfo.mPtr = GetFieldIDOrDie(env, clazz, "mPtr", "J");
gMessageQueueClassInfo.dispatchEvents = GetMethodIDOrDie(env, clazz,
"dispatchEvents", "(II)I");
return res;
}
在MessagQueue对象的构造方法中调用nativeInit JIN方法在此方法中创建了NativeMessageQueue对象。在register_android_os_MessageQueue方法中mPtr指向了java中MessageQueue的成员变量mPtr
NativeMessageQueue对象在创建的过程中,又会在内部调用C++的Looper对象
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
首先调用C++层的Looper类的静态成员函数getForThread()来获取当前线程的Looper对象。如果没有创建过就会创建一个C++层的Looper对象,并保存在NativeMessageQueue类的成员变量mLooper中,然后调用Looper的静态函数setForThread将当前线程关联起来。
C++ Looper类的创建过程中,又在内部创建一个管道
Looper::Looper(bool allowNonCallbacks)
: mAllowNonCallbacks(allowNonCallbacks),
mSendingMessage(false),
mPolling(false),
mEpollRebuildRequired(false),
mNextRequestSeq(0),
mResponseIndex(0),
mNextMessageUptime(LLONG_MAX) {
mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0, "Could not make wake event fd: %s", strerror(errno));
AutoMutex _l(mLock);
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
// Close old epoll instance if we have one.
if (mEpollFd >= 0) {
mEpollFd.reset();
}
// Allocate the new epoll instance and register the wake pipe.
mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(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.get();
int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s",
strerror(errno));
for (size_t i = 0; i < mRequests.size(); i++) {
const Request& request = mRequests.valueAt(i);
struct epoll_event eventItem;
request.initEventItem(&eventItem);
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
request.fd, strerror(errno));
}
}
}
在Looper中会创建mWakeEventFd,它是unique_fd类型的,在其中会创建一个管道。这个管道在消息循环中起到的作用非常大。首先当一个线程没有消息需要处理是,它就会睡眠在这个管道的读端文件描述符上,直到有新的消息需要处理为止;其次当其他线程向这个线程的消息队列发送一个消息之后,其他线程就会通过这个写端文件描述符往这个管道写入一个数据,从而将这个线程唤醒,以便对刚才发送到消息队列中的消息进行处理。