前置知识1:
学习任何知识都是要有一定的前置条件的,比如你要先识字才能“看懂”我这篇文章…
在全面了解Android消息处理机制之前,我希望读者对该机制最好要有一定的了解,至少知道主要由哪些类实现了该机制。
如果你还能看得懂c/c++代码,精通Linux内核,对pipe、eventfd和IO多路复用epoll机制都有深入的了解,那么我劝你就别看了…
本文的侧重点主要在于消息机制中的阻塞和唤醒上,对于Java层面的组成关系会简单的带过,这部分的内容已经烂大街了,如果想对于Java层的源码逐行分析请看下面的源码分析(
点了之后先不要打我,我其实真的是准备自己写一篇的
目录
主要组成
Android系统中主要由MessageQueue、Looper和Handler来实现Android应用程序的消息处理机制的。
MessageQueue
用来描述消息队列Looper
用来创建消息队列,以及开启消息循环Handler
用来发送和处理消息
创建过程
frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
...省略部分代码...
//调用了Looper构造函数,创建了MessageQueue消息队列
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
//开启消息循环
Looper.loop();
}
frameworks/base/core/java/android/os/Looper.java
public static void prepareMainLooper() {
prepare(false);
...省略部分代码...
}
private static void prepare(boolean quitAllowed) {
...省略部分代码...
//通过Looper构造函数创建对象,放入ThreadLocal里保证线程唯一
sThreadLocal.set(new Looper(quitAllowed));
}
//Looper的构造函数 内部调用了MessageQueue的构造函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
frameworks/base/core/java/android/os/MessageQueue.java
//用来保存nativeMessageQueue的指针对应的内存地址
private long mPtr; // used by native code
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
//【重点1】
mPtr = nativeInit();
}
Android消息处理机制中三个实现类的其中两个就这么简简单单的被创建出来了。通过这个调用顺序我们可以了解到 ActivityThread
构建了Looper
对象,Looper
对象构建了MessageQueue
对象。
如果抛开MessageQueue
构造函数中的nativeInit()
函数,我相信大部分Android开发者都能看懂上面的代码,到这里Java
层主要组成部分的Looper
对象和MessageQueue
对象都创建都完成了。
这里为什么提“Java
层主要组成部分”这个词汇,其实是因为我们的消息机制的组成不单单由Java
层构成,还由C/C++
层面的源码构成。就像我们Android系统一样
而C/C++
这部分的入口就在这个nativeInit()
函数中。接下来我们就直接分析这个函数。这个函数从名字上可以看出是一个JNI
调用。对应的是底层的C/C++
代码。如果你看不懂C/C++
代码也不要紧,先跟着看,我会最后尽量用通俗易懂的语言来描述他们之间的关系。
这里我们先来看一下Java
方法和C/C++
函数的对应关系,消息机制中所有的JNI
调用都可以从这里找到对应,这部分内容都在android_os_MessageQueue.cpp
文件中
frameworks/base/core/jni/android_os_MessageQueue.cpp
class NativeMessageQueue : public MessageQueue, public LooperCallback {
public:
//函数声明 构造函数
NativeMessageQueue();
virtual ~NativeMessageQueue();
virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj);
//函数声明 在Java层对应nativePollOnce
void pollOnce(JNIEnv* env, jobject obj, int timeoutMillis);
//函数声明 在Java层对应nativeWake
void wake();
void setFileDescriptorEvents(int fd, int events);
virtual int handleEvent(int fd, int events, void* data);
//3个私有的成员变量
private:
JNIEnv* mPollEnv;
jobject mPollObj;
jthrowable mExceptionObj;
};
//JNI调用对应函数关系
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 },
};
nativeInit()
函数最终调用的android_os_MessageQueue_nativeInit()
代码。
{
"nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit }
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
//调用NativeMessageQueue的构造函数
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return 0;
}
nativeMessageQueue->incStrong(env);
//强制类型转换reinterpret_cast 返回一个jlong类型 就是java的long类型
return reinterpret_cast<jlong>(nativeMessageQueue);
}
这个函数的实现通俗点的理解就是以下两点:
-
通过调用
NativeMessageQueue
构造函数创建一个NativeMessageQueue*
的指针变量nativeMessageQueue
,可以理解成Java
对象引用。 -
将
nativeMessageQueue
指针变量强制类型转换成Java
的long
类型,通过函数返回值赋值给Java
层的MessageQueue
中成员变量mPtr
,可以理解成mPtr
保存了nativeMessageQueue
这个指针变量的的内存地址
这样MessageQueue
和NativeMessageQueue
就建立了一定的关联。
mPtr = nativeInit();
long mPtr = nativeMessageQueued 的内存地址 0x00009527; //这个我瞎写的地址啊!
这里我们看下NativeMessageQueue
构造函数,发现这里又调用了Looper
的构造函数,这里的Looper
可不是Java
层的Looper
而是位于C/C++
层的Looper
//NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
//内部由调用了Looper的构造函数 此Looper不是Java层的Looper而是C/C++层的Looper
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
总结:
MessageQueue
通过JNI
调用构建了NativeMessageQueue
对象,并建立关联;