当前位置:操作系统 > 安卓/Android >>

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 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,