Android Handler中计时延迟的补偿方法

来源:互联网 发布:待机时间长的平板知乎 编辑:程序博客网 时间:2024/06/05 19:01

--- by Zhongxiang.Huang

近段时间,在开发项目过程中遇到一个双重计时不准确的问题,该项目功能是计算手机屏幕产生蓝光的能量值;原理大概是这样:设置好屏幕亮度,纯色屏,计算屏幕在20s时间内发出的蓝光能量值,然后在这20s内,还要分开100次(这里以100次举例)来分别计算,最后算总和,计算方法这里就不阐述了,因此就涉及了双重的计时需求,一个是20s单次计时,一个是20s内100次小计时,每个小计时时间是0.2s,需每隔0.2s得计算一次蓝光能量值。

开发过程中,我使用的计时方式是主线程中使用Handler,这种方式最简单,在主线程中通过handler.postDealyed(……, 200),并在onHandleMessage中继续post消息,这样就实现了每隔200ms进行一次消息循环。大家知道,这种方式下,如果使用handler.postDealyed(……, 200)方式来进行计时,是不准确的,有误差,误差的原因在于在你收到消息,到你重新发出handler.postDealyed的时间,并不是瞬间完成的,这里面有很多逻辑处理的时间,况且handler本身也是耗损性能的,所以消息并不可能按照理想的200ms延迟来进行发送,这就导致了误差的累积。而项目中对于这样的时间精确度是不能接受的,因为这样就不能达到预期的设计效果,因误差的影响,计时的超时,可能就做不到预设定的每隔0.2s计算一次,有时可能隔了0.3s、0.4s,从而就做不到在20s内计算100次的目的,常常发现预计100次只有98次或95次被完成。
所以,我们每次在post的时候,都需要对计时进行补偿,怎么做呢? 我们知道,Android中有很多计时的控件,我们这里对TextClock查看其源码,研究其是如何处理这个问题的,于是找到了这段代码:
private final Runnable mTicker = new Runnable() {
        public void run() {
            onTimeChanged();

            long now = SystemClock.uptimeMillis();
            long next = now + (1000 - now % 1000);

            getHandler().postAtTime(mTicker, next);
        }
    };

我先前是通过postDelay来触发消息事件的,但这里系统使用了postAtTime,这是为什么呢?再看前面两行代码,代个值进去试下,假如now取出来是1200,那么next = 1200 + (1000 - 1200 % 1000)也就是next= 2000。虽然我们前一次本该在1000触发的事件,被各种逻辑延迟到1200,如果用postDelay,延迟被累积了,但如果用这种方式,误差就会被补偿,因此问题也就解决了。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 想进部队体检没过怎么办 大腿跟小腿不直怎么办 腿被车门夹了怎么办 脚出汗穿凉鞋滑怎么办 玩游戏手出汗屏幕滑怎么办 新买的鞋子臭怎么办 当公民利益受到侵犯怎么办 唇钉里面长肉怎么办 宝宝舔了一口酒怎么办 头被玻璃门撞了怎么办 30多了还一事无成 未来怎么办 27岁失业了该怎么办 无业证明不给开怎么办 典型的缺乏运动的肥胖怎么办 30岁了不想结婚怎么办 专家解释欠30万怎么办 欠医院十几万钱怎么办 当你迷茫的时候怎么办 被骗了一年的积蓄怎么办 当兵身高视力都不够怎么办 当兵中途不想当了怎么办 当兵后不想当了怎么办 在泰国想剪头发怎么办 省二证书丢了怎么办 职称计算机级别报错怎么办 科一不会用电脑怎么办 西安科目三挂了怎么办 我有c照想考a照怎么办 叉车证单位不给怎么办 刚练科目三害怕怎么办 摩托科目一考不过怎么办 人老了视力不好怎么办 2岁宝宝视力不好怎么办 唱歌音总是唱不准怎么办 考级没地方练琴怎么办 少儿声乐唱不准音该怎么办 学历认证报告编号忘记了怎么办 自考挂科10门了怎么办 高中的会考没过怎么办 毕业证和学位证丢了怎么办 大学毕业证学位证丢了怎么办