该文章属于Android Handler系列文章,如果想了解更多,请点击
《Android Handler机制之总目录》
前言
在前面的文章中我们讲解了Handler、Looper、MessageQueue的具体关系,了解了具体的消息循环的流程。下面将一起来探讨最为整个消息循环的消息载体Message。
Message中可以携带的信息
Message中可以携带的数据比较丰富,下面对一些常用的数据进行了分析。
/**
* 用户定义的消息代码,以便当接受到消息是关于什么的。其中每个Hanler都有自己的命名控件,不用担心会冲突
*/
public int what;
/**
* 如果你只想存很少的整形数据,那么可以考虑使用arg1与arg2,
* 如果需要传输很多数据可以使用Message中的setData(Bundle bundle)
*/
public int arg1;
/**
* 如果你只想存很少的整形数据,那么可以考虑使用arg1与arg2,
* 如果需要传输很多数据可以使用Message中的setData(Bundle bundle)
*/
public int arg2;
/**
* 发送给接受方的任意对象,在使用跨进程的时候要注意obj不能为null
*/
public Object obj;
/**
* 在使用跨进程通信Messenger时,可以确定需要谁来接收
*/
public Messenger replyTo;
/**
* 在使用跨进程通信Messenger时,可以确定需要发消息的uid
*/
public int sendingUid = -1;
/**
* 如果数据比较多,可以直接使用Bundle进行数据的传递
*/
Bundle data;
其中关于what的值为什么不会冲突的原因是,之前我们讲过的handler是与线程进行绑定的。也就是说不同消息循环消息的发送,处理的线程是不一样的。当然是不会冲突的。对于Messenger,因为涉及到Binder机制,这里就不过多的描述了,有兴趣的小伙伴可以自行查询相关资料学习。
创建消息的方式
官方建议使用Message.obtain()系列方法来获取Message实例,因为其Message实例是直接从Handler的消息池中获取的,可以循环利用,不必另外开辟内存空间,效率比直接使用new Message()创建实例要高。其中具体创建消息的方式,我已经为大家分好类了。具体分类如下:
//无参数
public static Message obtain() {...}
//带Messag参数
public static Message obtain(Message orig) {}
//带Handler参数
public static Message obtain(Handler h) {}
public static Message obtain(Handler h, Runnable callback){}
public static Message obtain(Handler h, int what){}
public static Message obtain(Handler h, int what, Object obj){}
public static Message obtain(Handler h, int what, int arg1, int arg2){}
public static Message obtain(Handler h, int what,int arg1, int arg2, Object obj) {}
其中在Message的obtain带参数的方法中,内部都会调用无参的obtain()方法来获取消息后。然后并根据其传入的参数,对Message进行赋值。(关于具体的obtain方法会在下方消息池实现原理中具体描述)
消息池实现原理
既然官方建议使用消息池来获取消息,那么在了解其内部机制之前,我们来看看Message中的消息池的设计。具体代码如下:
private static final Object sPoolSync = new Object();//控制获取从消息池中获取消息。保证线程安全
private static Message sPool;//消息池
private static int sPoolSize = 0;//消息池中回收的消息数量
private static final i