Android消息机制Message消息池

来源:互联网 发布:Execl数据分析证书 编辑:程序博客网 时间:2024/05/22 15:30

这篇文章主要说下Android在实现Message类的时候使用的一个所谓的消息池的问题。

我们在使用Android的消息循环时,一般按照下面的方式使用,为了使线程具有消息循环如下:

//实现自己的Handler类,重写handlerMessage()方法

[java] view plain copy
  1. private class MyHandler extends Handler{  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         if(msg.what==1){  
  5.             textView.setText(""+msg.arg1);//获得传递过来的数据  
  6.         }  
  7.         super.handleMessage(msg);  
  8.     }     
  9. }  


在线程的run()方法里调用Looper.prepare(),实例化一个Handler对象,调用Looper.loop()使线程进入消息循环

[java] view plain copy
  1. public void run(){  
  2.     Looper.prepare();  
  3.     //dosomething else  
  4.    handler=new MyHandler();  
  5.    Looper.loop();  
  6. }  

Handler对象的实例话必须在Looper.prepare()之后。

当我们要给具有消息循环的线程发送消息时,我们先要获得具有消息循环的线程的 Handler 对象(或者先获取具有消息循环的线程的Looper对象,再使用这个Looper对象构造Handler对象),构造一个Message对象,然后调用Handler对象的sendMessage方法

[java] view plain copy
  1. Message message=Message.obtain();  
  2. message.what=1;  
  3. message.arg1=count;  
  4. handler.sendMessage(message);  

 

说了这么多,现在就来说下Message里的消息池问题,我们先看Message的静态成员方法 Message.obtain();


 

[java] view plain copy
  1. // sometimes we store linked lists of these things  
  2. /*package*/ Message next;  
  3. private static final Object sPoolSync = new Object();  
  4. private static Message sPool;  
  5. private static int sPoolSize = 0;  
  6. private static final int MAX_POOL_SIZE = 50;  
  7. /** 
  8.  * Return a new Message instance from the global pool. Allows us to 
  9.  * avoid allocating new objects in many cases. 
  10.  */  
  11. public static Message obtain() {  
  12.     synchronized (sPoolSync) {  
  13.         if (sPool != null) {  
  14.             Message m = sPool;  
  15.             sPool = m.next;  
  16.             m.next = null;  
  17.             sPoolSize--;  
  18.             return m;  
  19.         }  
  20.     }  
  21.     return new Message();  
  22. }  

在这个类中sPool代表这个消息池的头消息,sPoolSize表示消息池中可用的消息的个数即没有被使用的Message对象的个数,next表示下一个可用的消息Message对象。
可以看到obtain()方法说会从全局消息池中取消息,假设是第一次获得一个Message对象,那么sPool肯定为null,也就说第一次获取消息Message对象时是还没有消息池的,必须通过Message的构造方法获取一个Message对象的,Message的构造方法什么也没干

[java] view plain copy
  1. /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). 
  2. */  
  3. public Message() {  
  4. }  

那这就有点奇怪了,它的消息池是什么时候初始化呢?难道不是先new几个Message对象然后存着?这是我们注意到Message类的另一个成员方法recycle(),注意这个方法不是静态的.

[java] view plain copy
  1. /** 
  2.  * Return a Message instance to the global pool.  You MUST NOT touch 
  3.  * the Message after calling this function -- it has effectively been 
  4.  * freed. 
  5.  */  
  6. public void recycle() {  
  7.     clearForRecycle();  
  8.   
  9.     synchronized (sPoolSync) {  
  10.         if (sPoolSize < MAX_POOL_SIZE) {  
  11.             next = sPool;  
  12.             sPool = this;  
  13.             sPoolSize++;  
  14.         }  
  15.     }  
  16. }  

 

里面的clearForRecycle()方法只是把一些成员变量置为null,以便垃圾回收

[java] view plain copy
  1. /*package*/ void clearForRecycle() {  
  2.     flags = 0;  
  3.     what = 0;  
  4.     arg1 = 0;  
  5.     arg2 = 0;  
  6.     obj = null;  
  7.     replyTo = null;  
  8.     when = 0;  
  9.     target = null;  
  10.     callback = null;  
  11.     data = null;  
  12. }  

 

从这里我们就可以发现,消息池中Message的对象是通过recycle()放进去的. 但是我们自己并没有调用recycle()方法,那这个方法是在哪里调用的?看下Looper的源码就知道,在Looper的loop()方法的最后调用了Message对象msg的recycle()方法来回收这个Message对象,通过recycle()将这个Message对象的数据清空然后链接到消息池中(采用的头插法)。

0 0
原创粉丝点击