android源码学习-Handler机制及其六个核心点

本文详细探讨了Android中的Handler机制,包括Callback和handleMessage的执行优先级、MessageQueue的next()方法、nativePollOnce()的原理、IdleHandler的触发与执行流程,以及Message执行监听的应用。通过源码解析,阐述了主线程的消息处理过程和性能监控方法。
摘要由CSDN通过智能技术生成

方式一直接执行Message中的callBack;

方式二自定义Handler,重写其handleMessage方法。

这里我们可以明显看到,callBack的优先级会更高。这是技术点3:CallBack和handleMessage哪个会优先被执行

public void dispatchMessage(@NonNull Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

handleCallBack中就是直接通过

message.callback.run();

执行Message的runnable任务。PS:run()是Runnable接口中定义的方法

五、MessageQueue.next()取消息


先看代码,具体分为下面的几个环节。

Message next() {

for (;😉 {

if (nextPollTimeoutMillis != 0) {

Binder.flushPendingCommands();

}

nativePollOnce(ptr, nextPollTimeoutMillis);//4.1 nativePollOnece

synchronized (this) {

// Try to retrieve the next message. Return if found.

final long now = SystemClock.uptimeMillis();

Message prevMsg = null;

Message msg = mMessages;

…屏障消息相关代码先忽略

if (msg != null) {//4.2 寻找可用message

if (now < msg.when) {

// Next message is not ready. Set a timeout to wake up when it is ready.

nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);

} else {

// Got a message.

mBlocked = false;

if (prevMsg != null) {

prevMsg.next = msg.next;

} else {

mMessages = msg.next;

}

msg.next = null;

if (DEBUG) Log.v(TAG, "Returning message: " + msg);

msg.markInUse();

return msg;

}

} else {

// No more messages.

nextPollTimeoutMillis = -1;

}

…idelHandler相关代码先忽略

}

}

5.1 nativePollOnce方法

这是一个native方法,阻塞的。我们上面所说的CPU休眠也就是通过nativePollOnce这个机制来实现的。调用这个方法的时候,CPU资源会被释放掉,直到被外界唤醒。底层的实现原理对应的是linux的epoll机制,这篇文章我们就不详细去分析了。我们只要知道其方法的功能就可以了。

nativePollOnce有两个参数,ptr和timeoutMillis

ptr可以理解为一个native标记的唯一值,用来识别绑定线程的。

timeoutMillis是超时时间。主要分为三种-1,0,>0。

=-1的时候是处于无限阻塞的状态,除非被外界唤醒。

=0的时候不会阻塞,会立马执行。

>0时会阻塞对应的时间,然后释放阻塞状态。

PS:nativePollOnce的native实现其实和安卓层有一些类似,也有一个阻塞的循环队列的。底层的实现机制是epoll,由于native层不是本文的核心,这里就不扩展介绍了,感兴趣的同学可以留言,我

5.2 遍历链表,寻找可以用的message

1.因为链表我们插入时是按照执行时间去插入的,所以最先执行的Message一定在链表的最头部;

2.首先获取一下当前系统非休眠状态时间;

3.首先尝试获取链表的头部,那么说明链表中无数据。则把nextPollTimeoutMillis赋值为-1,下一个循环时,就会进入无限阻塞状态,直接被唤醒。这里对应的就是2.5 章节时讲到的native唤醒机制。

4.如果头节点不为空,则判断其执行时间和当前时间做比较;

5.如果其执行时间小于当前时间,则计算差值nextPollTimeoutMillis。并且会跳出此次Message选择流程。并且在下一次循环的时候,nativePollOnce会使用该值休眠对应的时间。保证休眠时间一到,正好到了头节点的执行时间。

6.如果其执行时间是否大于当前时间,则表明该节点是可以被执行的。把头节点改成下一级节点。并且通过Message.markInUse标记当前Message已经被使用。

7.返回上一步查到的message对象

五、异步消息/屏障消息


技术点4:屏障异步消息的实现机制

1 屏障消息其实就是target为空的Message消息。

2 异步消息一定要搭配屏障消息来使用。

3 如果头节点为屏障消息时,

  • 24
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值