引言:
Android应用消息处理机制是怎么样的呢?
跟Native,Linux底层都有些什么关系呢?
概念与理解:
Android应用程序是通过消息来驱动的。
1)应用程序的每一个线程在启动的时候,都可以首先在内部创建一个消息队列,
2)然后进入消息循环,并不断检查他的消息队列是否又行的消息需要处理。
如果有:那么线程就会将它从消息队列中取出来,进行处理
如果没有:线程就会进入睡眠等待状态,直到有新的消息需要处理为止。
这样的就叫做:通过消息来驱动应用程序的执行了。
Android应用程序的消息处理机制是围绕消息队列来实现的。
一个线程拥有一个消息队列之后,就可以进入到一个消息循环中,同时其他线程以及线程本身可以往这个消息队列发送消息。以便可以在这个消息独立额被处理是执行一个特定的操作。这样我们就可以将消息机制分为两个阶段:消息队列的创建和消息队列的循环。消息队列的循环又可以分为:消息的发送和消息处理。
1、消息队列的创建
MessageQueue:此对象用来描述Android应用线程的消息队列。
Looper:此对象是用来实现循环的。
这两个对象在Java层和Native层都有实现。所以Android的消息循环机制不仅可以在Java代码中使用,也可以在C++的代码中使用。先看一个导图:
1)Java层有MessageQueue类和Looper类,Native层有NativeMessageQueue类和Looper类
2)Java中,每一个Looper对象内有一个MessageQueue类型的成员变量mQueue,指向一个MessageQueue;
3)Native中,每一个NativeMessageQueue对象内部都有一个类型为Looper的成员变量mLooper,指向Native层的Looper对象。
这样就让Java层和Native层各自吧MessageQueue和Looper关联在一起了。那Java层与Native层又是怎么关联在一起呢?答案是mPtr,这是MessageQueue的对象的一个类型为int型的成员变量,它是指向NativeMessageQueue的。
MessageQueue和Looper构成了一个消息循环的基础框架,那消息放哪里呢?
消息是用一个叫做Message的类型的成员变量mMessage来描述的。这个mMessage是属于MessageQueue对象的。MessageQueue,Looper,Message就构成了消息循环的所有元素了。
消息队列是怎么创建的呢?消息又是怎么加到消息队列去的呢?
Looper里面通过两个静态成员函数可以创建消息队列:
1)prepareMainLooper :应用程序主线程创建消息队列
2)prepare:子线程创建消息队列
当调用这两个静态成员函数进行消息队列创建时,Java层的Looper类就会在这个线程中创建一个Looper对象和一个MessageQueue对象。在创建Java层的MessageQueue对象的过程中,会调用nativeInit在C++层创建一个NativeMessageQueue对象和一个Looper对象。上面已经解释了Java层和Native层时怎么关联在一起的了。在创建NativeMessageQueue对象时,还会创建一个管道,这个管道的作用是什么呢?
当一个线程消息队列没有消息需要处理是,它就会在这个管道的读端文件描述符上进行睡眠等待,直到其他线程通过这个管道的写端文件描述符来唤醒它。也就是读端描述符可以睡眠,写端描述符可以唤醒
这两个描述符是属于Looper的静态成员变量:
mWakeReadPipeFd
mWakeWritePipeFd
是怎么支撑管道的睡眠和唤醒的呢?
system/core/libutils/Looper.cpp
主要是基于Linux的Epoll消息机制。如果一个epoll实例监听了大量的文件描述符的IO读写事件,但是只有少量的文件描述符是活跃的,即有少量的文件描述符会发生IO读写事件,那么这个epoll实例可以现住地减少CPU的使用率,从而提高系统性能的并发处理能力。
frameworks/base/core/java/android/os/Looper.java