Android线程间通信的Message机制
1.1.Message
代码在frameworks\base\core\java\android\Os\Message.java中。
Message.obtain函数:有多个obtain函数,主要功能一样,只是参数不一样。作用是从Message Pool中取出一个Message,如果Message Pool中已经没有Message可取则新建一个Message返回,同时用对应的参数给得到的Message对象赋值。
Message Pool:大小为10个;通过Message.mPool->(Message并且Message.next)->(Message并且Message.next)->(Message并且Message.next)...构造一个Message Pool。Message Pool的第一个元素直接new出来,然后把Message.mPool(static类的static变量)指向它。其他的元素都是使用完的 Message通过Message的recycle函数清理后放到Message Pool(通过Message Pool最后一个Message的next指向需要回收的Message的方式实现)。下图为Message Pool的结构:
1.2.MessageQueue
MessageQueue里面有一个收到的Message的对列:
MessageQueue.mMessages(static变量)->( Message并且Message.next)-> ( Message并且Message.next)->...,下图为接收消息的消息队列:
上层代码通过Handler的sendMessage等函数放入一个message到MessageQueue里面时最终会调用MessageQueue的 enqueueMessage函数。enqueueMessage根据上面的接收的Message的队列的构造把接收到的Message放入队列中。
MessageQueue的removeMessages函数根据上面的接收的Message的队列的构造把接收到的Message从队列中删除,并且调用对应Message对象的recycle函数把不用的Message放入Message Pool中。
1.3.Looper
Looper对象的创建是通过prepare函数,而且每一个Looper对象会和一个线程关联
Java代码
1. public static final void prepare() {
2. if (sThreadLocal.get() != null) {
3. throw new RuntimeException("Only one Looper may be created per thread");
4. }
5. sThreadLocal.set(new Looper());
6. }
Looper对象创建时会创建一个MessageQueue,主线程默认会创建一个Looper从而有MessageQueue,其他线程默认是没有 MessageQueue的不能接收Message,如果需要接收Message则需要通过prepare函数创建一个MessageQueue。具体操作请见示例代码。
Java代码
1. private Looper() {
2. mQueue = new MessageQueue();
3. mRun = true;
4. mThread = Thread.currentThread();
5. }
prepareMainLooper函数只给主线程调用(系统处理,程序员不用处理),它会调用prepare建立Looper对象和MessageQueue。
Java代码
1. public static final void prepareMainLooper() {
2. prepare();
3. setMainLooper(myLooper());
4. if (Process.supportsProcesses()) {
5. myLooper().mQueue.mQuitAllowed = false;
6. }
7. }
Loop函数从MessageQueue中从前往后取出Message,然后通过Handler的dispatchMessage函数进行消息的处理(可见消息的处理是Handler负责的),消息处理完了以后通过Message对象的recycle函数放到Message Pool中,以便下次使用,通过Pool的处理提供了一定的内存管理从而加速消息对象的获取。至于需要定时处理的消息如何做到定时处理,请见 MessageQueue的next函数,它在取Message来进行处理时通过判断MessageQueue里面的Message是否符合时间要求来决定是否需要把Message取出来做处理,通过这种方式做到消息的定时处理。
Java代码
1. public static final void loop() {
2. Looper me = myLooper();
3. MessageQueue queue = me.mQueue;
4. while (true) {
5. Message msg = queue.next(); // might block
6. //if (!me.mRun) {
7. // break;
8. //}
9. if (msg != null) {
10. if (msg.target == null) {
11. // No target is a magic identifier for the quit message
12. return;
13. }
14.
15. if (me.mLogging!= null)
16. me.mLogging.println(">>>>> Dispatching to " + msg.target + " "+ msg.callback + ": " + msg.what);
17. msg.target.dispatchMessage(msg);
18. if (me.mLogging!= null)
19. me.mLogging.println("<<<<< Finished to" + msg.target + " "+ msg.callback);
20. msg.recycle();
21. }
22. }
23. }
1.4.Handler
Handler的构造函数表示Handler会有成员变量指向Looper和MessageQueue,后面我们会看到没什么需要这些引用;至于callback是实现了Callback接口的对象,后面会看到这个对象的作用。
Java代码
1. public Handler(Looper looper, Callback callback) {
2. mLooper = looper;
3. mQueue = looper.mQueue;
4. mCallback = callback;
5. }
6.
7. public inte易做图ce Callback {
8. public boolean handleMessage(Message msg);
9. }
获取消息:直接通过Message的obtain方法获取一个Message对象。
Java代码
1. public final Message obtainMessage(int what, int arg1, int arg2, Object obj){
2. return Message.obtain(this, what, arg1, arg2, obj);
3. }
发送消息:通过MessageQueue的enqueueMessage把Message对象放到MessageQueue的接收消息队列中
Java代码
1. public boolean sendMessageAtTime(Message msg, long uptimeMillis){
2. boolean sent = false;
3. MessageQueue queue = mQueue;
4. if (queue != null) {
5. msg.target = this;
6. sent = queue.enqueueMessage(msg, uptimeMillis);
7. } else {
8. RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");
9. Log.w("Looper", e.getMessage(), e);
10. }
11. return sent;
12. }
线程如何处理MessageQueue中接收的消息:在Looper的loop函数中循环取出MessageQueue的接收消息队列中的消息,然后调用 Hander的dispatchMe
补充:移动开发 , Android ,