Handler消息机制(native层)
1.简介
在介绍Handler消息机制(Java层)时,我们看到了Java层的MessageQueue中调用了几个native方法。除此之外,native层也有一套完善的消息机制,用于处理native的消息。
首先来看下native层handler消息的类图:
从图中可以看到,native层的消息机制关键元素和Java层的消息机制的关键元素基本一致,分别包括Looper、MessageQueue、Handler、Message这几个关键元素。除了MessageQueue是Java层与Native层相关联的,其余的几个元素都是不相关联的,但元素的功能基本是一致的,只是Java层和Natvie层的实现方式不一样的。
接下来将从MessageQueue中的native方法开始分析Native层的Handler消息机制。
2.MessageQueue的native方法
在Java层的MessageQueue中定义了几个native方法:
public final class MessageQueue {
......
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
......
}
nativeInit方法
在构建Java层的MessageQueue时,会调用nativeInit()方法进行初始化。
2.1 MessageQueue()
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();// 保存native层的MessageQueue引用,见2.1
}
在构建MessageQueue的过程中,会通过JNI调用native层的android_os_MessageQueue_nativeInit方法进行初始化。
2.2 android_os_MessageQueue_nativeInit()
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();// 构建MessageQueue,见2.3
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}
nativeMessageQueue->incStrong(env);
return reinterpret_cast<jlong>(nativeMessageQueue);//返回到Java层
}
2.3 NativeMessageQueue()
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();//获取该线程关联的Looper
if (mLooper == NULL) {
mLooper = new Looper(false);// 创建一个Looper对象,见2.4
Looper::setForThread(mLooper);// 将该Looper保存到线程的TLS中
}
}
在Native层的MessageQueue中,包含了一个Looper对象,该Looper对象是与线程相关的,保存在线程的TLS中,这个与Java层的处理方式一样。如果该线程的Looper对象存在,则直接返回;如果不存在,则创建一个Looper,并保存到该线程的TLS中。
2.4 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);// 构建一个唤醒事件的文件描述符fd
AutoMutex _l(mLock);
rebuildEpollLocked();// 重构epoll事件,见2.5
}
eventfd函数会创建一个事件对象(eventfd object),用来实现进程(线程)间的等待(wait)/通知(notify)机制(Linux管道pipe也可以实现该功能),内核会为这个对象维护一个64位的计数器。eventfd的函数定义如下:
#include<sys/eventfd.h>
int eventfd(unsigned int initval,int flags);
第一个参数initval用来初始化这个计数器,一般初始化为0;
第二个参数为标志位,可选的值为ÿ