
send系列的方法:8个(注意:executeOrSendMessage()方法为hide修饰)
sendEmptyMessage()方法分析
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
用于发送一个空消息的方法,传入的参数为int,表示Message对象持有的int值
1、直接调用sendEmptyMessageDelayed()方法,并将传入的what值和一个数字0,一起传了进去
2、为调用者返回sendEmptyMessageDelayed()方法的返回值
true表示发送消息成功
false表示发送消息失败
sendEmptyMessageDelayed()方法分析
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
用于发送一条延迟发送的消息,传入的整型参数what表示Message对象持有的int值,传入的long型参数delayMillis表示延迟的毫秒数
1、从消息池获取一个Message对象
Message的obtain()方法为静态工厂方法,它用于返回一个Message对象,此Message由局部变量msg负责持有
2、为Message对象持有的what赋值
将传入的整型值what赋值给创建的Message对象msg持有上
3、通过调用sendMssageDelayed()方法完成发送工作
将创建的Message对象与传入的long型参数delayMillis同时传入sendMessageDelayed()到方法中,由该方法完成发送工作
4、向调用者返回sendMessageDelayed()的返回值
true表示发送消息成功
flase表示发送消息失败
sendMessageDelayed()方法分析
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
用于发送延迟消息的方法,传入的第一个参数为Message对象,传入的第二个参数为延迟发送的时间,单位:毫秒
1、检查消息延迟时间
首先判断延迟时间delayMillis是否小于0,针对这种情况会将delayMillis强制将赋值为0
2、计算出一个实际延迟的准确时间(开机至今的具体时间)
使用手机到现在的毫秒数System.uptimeMillis()与延迟时间delayMillis相加,得出一个具体的时间
3、调用sendMessageAtTime()方法发送消息
将传入的Message对象和计算后的具体发送时间传入到sendMessageAtTime()方法中
4、向调用者返回sendMessageAtTime()方法的结果
true表示发送消息成功
false表示发送消息失败
SystemClock.uptimeMillis() // 从手机开机到现在的毫秒数(手机睡眠的时间不包括在内)
System.currentTimeMillis() // 从1970年1月1日0时0分0秒到现在的毫秒数
sendMessageAtTime()方法分析
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
用于在指定时间发出消息的方法,传入的第一个参数表示Message对象,传入的第二个参数表示发送消息的具体时间
1、获取Handler对象持有的MessageQueue对象,并存储在本地
定义一个临时变量queue,负责存储Handler对象持有的MessageQueue对象mQueue
2、检查MessageQueue是否已创建
若局部变量queue为null,说明MessageQueue对象并没有创建,此时创建一个RuntimeException对象,并提示方法的使用者:this + " sendMessageAtTime() called with no mQueue"
看来Handler肯定重写了toString()方法,并在logcat中打印:RuntimeException的字符串信息,最后返回false
3、检查通过,MessageQueue已经创建后,则执行
调用enqueueMessage()方法用于发送消息,并传入MessageQueue对象、Message对象、以及发送消息的具体时间戳
4、向调用者返回enqueueMessage()方法的返回值
true表示消息发送成功
false表示消息发送失败
enqueueMessage()方法分析
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
用于实际向MessageQueue插入一条Message的方法,传入的第一个参数为MessageQueue对象,第二个参数为Message对象,第三个参数为插入消息的具体时间戳(1970年1月1日0时0分0秒距今)
1、为传入的Message对象持有的target赋值为当前Handler对象
传入的Message对象msg持有了一个target,此时target会指向发送的当前Handler对象,这也是为何Handler对象发送出去的消息,最后还能调用到Handler的handleMessage()方法的原因
2、检查异步消息标志位,并标记Message对象的类型
判断Handler对象持有的实例变量mAsynchronous,若mAsynchronous为true,说明发送的消息是异步消息,则调用Message对象的setAsynchronous()方法,并传入了true,表示传入的Message对象将成为异步消息。异步消息将会比同步消息优先执行(前提:同步屏障SyncBarrier)
3、通过MessageQueue的enqueueMessage()方法将Message插入到消息队列中
此MessageQueue对象也是Looper对象持有的MessageQueue对象,因Handler对象同时也持有这个MessageQueue对象,此时的Message对象会插入到MessageQueue对象持有的单链表队列中,enqueueMessage()接受的第一个参数是Message对象,第二个参数为消息具体执行的时间戳
4、向调用者返回插入结果
true表示插入消息成功
false表示插入消息失败
sendMessage()方法分析
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
用于发送Message对象的方法,传入的参数表示Message对象
1、调用了sendMessageDelayed方法进行发送工作,将Message对象和延迟时间0同时传了进去,0表示不延迟,立刻发送
2、向调用者返回发送结果
true表示发送消息成功
false表示发送消息失败
sendMessageAtFrontOfQueue()方法分析
public final boolean sendMessageAtFrontOfQueue(Message msg) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
用于向MessageQueue插队消息的方法,它会将Message对象插入到MessageQueue中的最前列,以保证插入的消息最先被Looper取出来,交给Handler处理
1、将Handler对象持有的MessageQueue对象保存在局部变量中
首先获得Handler持有的MessageQueue对象mQueue交给临时变量queue存储
2、检查消息队列,处理未创建消息队列的情况
判断MessageQueue能否为空,创建RuntimeException对象,然后并没有抛出这个异常对象,只是会在logcat中打印这条异常日志的情况,最后返回false代表发送Message失败。
3、消息队列创建的情况,执行后续发送动作
调用enqueueMessage()方法,为它传入MessageQueue对象,再传入一个Message对象,以及一个数字0,这个数字0表示延迟时间。
4、向调用者返回结果
返回enqueueMessage()方法的返回值
sendEmptyMessageAtTime()方法分析
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
用于在指定时间发送出一条只设置int值的Message对象,传入的第一个参数what表示Message对象持有的int值,传入的第二个参数表示指定的具体时间戳
1、创建一个Message对象,并保存在本地
Message的静态方法obtain()可以从消息池中返回一个Message对象,并保留在创建的局部变量msg中
2、将传入的what值保存在创建的Message对象中
传入的what值由创建的Message对象持有的实例变量what进行保存
3、调用sendMessageAtTime()方法进行发送工作,并将Message对象msg与延迟时间uptimeMillis传进去
4、向调用者返回sendMessageAtTime()方法的结果
true表示发送消息成功
false表示发送消息失败
executeOrSendMessage()方法分析
public final boolean executeOrSendMessage(Message msg) {
if (mLooper == Looper.myLooper()) {
dispatchMessage(msg);
return true;
}
return sendMessage(msg);
}
hide修饰的方法,用于直接在本地处理一条Message方法
1、检查Looper
判断Handler对象持有的Looper对象mLooper是否等于Looper.myLooper()对象,如果是在同一个线程下的Looper对象,则直接调用Handler对象的dispatchMessage()方法去处理Message对象,并返回结果为true,表示发送成功
2、Looper不同,表示不在一个线程下使用的情况
若执行该方法的线程与创建Handler的线程不是同一个,则调用sendMessage()方法进行Message对象的发送,并向调用者发送执行结果
总结
1、send系列的方法,最终都会执行到sendMessageAtTime()方法(除了sendMessageAtFrontOfQueue方法以及executeOrSendMessage方法与Handler创建时在同一个线程时)
2、消息的延迟时间都会加上一个SystemClock.uptimeMillis(),SystemClock.uptimeMillis()是开机至今的时间戳
3、sendMessageAtFrontOfQueue()方法,用于将Message插入到消息队列最开头,所以延迟时间为0
4、executeOrSendMessage()方法,调用该方法的线程与创建Handler对象的线程是同一个时,该方法支持在Handler对象中直接处理Messag对象,而只有不在同一个线程时,才将Message传递到MessageQueue对象中(可惜该方法是hide修饰)
5、Handler对象持有一个mAsynchronous标志位,它代表即将要发送消息的类型,当mAsynchronous为true时,说明Handler发出的是异步消息(平时咱们发送的是同步消息)。异步消息能被优先执行的前提:同步屏障调用MessageQueue.postSyncBarrier()方法实现,该方法会发出一个Message.target == null的消息,我们平时用的Handler对象的target不可能为null,所以我们发出的消息可以是异步消息,但是并没有同步屏障,该异步消息还是不会得到执行!
6、我们也无法调用MessageQueue的postSyncBarrier()方法(hide修饰),那谁可以设置同步屏障呢?或者说谁发出来一个Message.target == null的消息?正是大名鼎鼎的ViewRootImpl.scheduleTraversals中可以发出同步屏障,搭上它的顺风车,我们自己的异步消息也会得到优先执行!
本文详细剖析了Android中Handler机制的send系列方法,包括sendEmptyMessage、sendEmptyMessageDelayed等,揭示了消息发送、延迟与异步处理的内部流程。
3347





