一文带你深入理解Android-Handler机制(深入至native层)

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没
  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值