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

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

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

private class MyHandler extends Handler{@Overridepublic void handleMessage(Message msg) {if(msg.what==1){textView.setText(""+msg.arg1);//获得传递过来的数据}super.handleMessage(msg);}}


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

public void run(){    Looper.prepare();    //dosomething else   handler=new MyHandler();   Looper.loop();}

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

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

Message message=Message.obtain();message.what=1;message.arg1=count;handler.sendMessage(message);

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


    // sometimes we store linked lists of these things    /*package*/ Message next;    private static final Object sPoolSync = new Object();    private static Message sPool;    private static int sPoolSize = 0;    private static final int MAX_POOL_SIZE = 50;    /**     * Return a new Message instance from the global pool. Allows us to     * avoid allocating new objects in many cases.     */    public static Message obtain() {        synchronized (sPoolSync) {            if (sPool != null) {                Message m = sPool;                sPool = m.next;                m.next = null;                sPoolSize--;                return m;            }        }        return new Message();    }

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

    /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).    */    public Message() {    }

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

    /**     * Return a Message instance to the global pool.  You MUST NOT touch     * the Message after calling this function -- it has effectively been     * freed.     */    public void recycle() {        clearForRecycle();        synchronized (sPoolSync) {            if (sPoolSize < MAX_POOL_SIZE) {                next = sPool;                sPool = this;                sPoolSize++;            }        }    }

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

    /*package*/ void clearForRecycle() {        flags = 0;        what = 0;        arg1 = 0;        arg2 = 0;        obj = null;        replyTo = null;        when = 0;        target = null;        callback = null;        data = null;    }

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

更多相关文章

  1. 在Android中使用Handler和Thread线程执行后台操作
  2. 强制结束Android进程
  3. Android多媒体播放器源码解析(stagefright框架)
  4. Android(安卓)configChanges属性总结
  5. 横竖屏切换时候activity的生命周期,重要参数:android:configChange
  6. android通过chmod命令实现文件权限修改
  7. Android(安卓)AIDL接口定义语言
  8. android TextView的字体颜色设置的多种方法(续)
  9. Android,采用AIDL编写接口实现IPC 入门

随机推荐

  1. [Android] 开发资料收集:动态加载、插件化
  2. 浅谈Android五大布局——LinearLayout、F
  3. Android单元测试全解
  4. 源码分析Android(安卓)应用进程的启动过
  5. android通过adb wireless的使用
  6. Android知识点记录: 使用代码设置 androi
  7. Android 4.1源代码今日将发布
  8. Android活动的四种启动模式
  9. Android(安卓)热修复框架 AndFix (一)
  10. Android 如何在App中启动系统闹钟