return;
}
}
//Handler自身的回调方法handleMessage()
handleMessage(msg);
}
}
一般我们都会在创建handler时重写handleMessage方法。
发送消息
在使用handler时,我们可以通过调用handler的发送消息方法,向队列中抛message。
具体方法有:
sendMessage(Message e)
sendMessageDelayed(Message e)
sendEmptyMessage(int what)
obtainMessage()
obtainMessage(int what)
post(Runnable r)
推荐使用obtainMessage()方法,因为不需要外部去new Message()传进来,而是使用handler内部消息池中的消息。减少创建Message所带来的开销
无论哪个方法最终都会走到这个方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
我们重点讲解下这个方法
参数:
-
queue:消息队列,就是handler中持有的消息队列,也就是Looper初始化时创建的queue
-
message:消息体
-
uptimeMillis:消息触发的时间,我们可以通过sendMessageDelay()来延迟消息的触发。当前时间13:10:10,调用sendMessageDelay(message,10000),表示10秒钟后触发消息,那么uptimeMillis的值就是13:10:20所对应的毫秒值,具体的转换实现如下:系统时间+延迟时间
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
由此可见,如何实现的延迟发送,并没有在handler中实现,而是带着延迟时间一起传递了messageQueue,由它去实现
另外还有一个逻辑,即若Handler是同步的,则设置消息是同步的,这个先不管。
移除消息
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null); 【见 4.5】
}
同样丢给了MessageQueue去处理
MessageQueue
MessageQueue不仅是逻辑的中心,并且是与native交互的类,一些比较重要的逻辑,例如阻塞与唤醒,是由native实现的
创建MessageQueue
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
//通过native方法初始化消息队列,其中mPtr是供native代码使用
mPtr = nativeInit();
}
在创建Looper()时,会创建MessageQueue,这里直接调用了native方法,返回的mPtr参数是调用其他native方法时需要的参数,这里我们先不过多讨论。在讲解native部分时讨论
循环消息
整个handler工作原理的逻辑中心就是MessagwQueue的next()方法以及enqueueMessage()方法。其实MessageQueue中维护了一份链表,元素是Message,我们从Message类的定义中可以看出定义了【Message next】;enqueueMessage()方法就是将Message插入到链表合适的位置(按,delay的顺序排序),next()方法就是从链表中取出合适的Message处理。下边我们具体看
enqueueMessage
boolean enqueueMessage(Message msg, long when) {
// 每一个普通Message必须有一个target,除了屏障消息
if (msg.target == null) {
throw new IllegalArgumentException(“Message must have a target.”);
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) { //正在退出时,回收msg,加入到消息池
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
/**
- 1.p为null 代表链表为空,新进来的msg作为链表第一个元素
- 2.msg的触发时间是队列中最早的,则插入到p的前边,并作为mMessages
*/
if (p == null || when == 0 || when < p.when) {
//p为null(代表MessageQueue没