【源码分析】CountDownTimer倒计时为何如此优雅

【毕设实战】飞行器目标识别系统:基于YOLOv5的智能检测全流程教程,助你毕设脱颖而出 亲爱的同学,毕设是不是让你既期待创新又担心技术门槛?如果你的毕设方向是计算机视觉、智能检测,那这个绝对能成为你的“毕设王牌”。从数据准备到界面开发,我会把整个项目拆成“傻瓜式”步骤,让你能一步步做出属于自己的毕设成果。 阅读详情

CountDownTimer是一个抽象类,它有两个抽象方法需要调用者去实现。
我们可以直接以匿名类形式使用:

new CountDownTimer(50 * 1000, 2 * 1000) {

            @Override
            public void onTick(long millisUntilFinished) {
                //do sth
            }

            @Override
            public void onFinish() {
                //do sth
            }
        }.start();

也可以这样使用:

private class MyCountDownTimer extends CountDownTimer {

        MyCountDownTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            //do sth
        }

        @Override
        public void onFinish() {
            //do sth
        }
    }
myCountDownTimer = new MyCountDownTimer(50 * 1000, 2 * 1000);
myCountDownTimer.start(); 

以上两种方法都可以开始一个50s的倒计时,每隔2s回调onTick方法,参数为倒计时剩余时间,50s后回调onFinish方法。

不管哪种方法,都很是优雅,简单轻松地就实现了倒计时功能。
内部是如何实现的呢?
先看一下它唯一的构造方法:

    /**
     * @param millisInFuture The number of millis in the future from the call
     *   to {@link #start()} until the countdown is done and {@link #onFinish()}
     *   is called.
     * @param countDownInterval The interval along the way to receive   
     *   {@link #onTick(long)} callbacks.
     */
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

这里传入了两个参数,分别表示倒计时时间和回调onTick方法的间隔时间(以下简称间隔时间)。

调用start方法后倒计时就开始了,我们看一下start方法:

 /**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }

第6行对倒计时时间进行判断,如果时间<=0,则直接回调onFinish方法。
第10行计算出倒计时应该停止的时间,存入变量mStopTimeInFuture。
第11行用mHandler发出了一条消息,我们看一下mHandler:

  // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } else if (millisLeft < mCountdownInterval) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };

第12行计算出倒计时剩余时间,存入变量millisLeft。
接着分为3种情况展开,
第一种情况:
当millisLeft<=0时,直接回调onFinish方法。
第二种情况:
当millisLeft<间隔时间时,延迟millisLeft用mHandler发出消息,届时将再次进入handleMessage方法,millisLeft<0,成为第一种情况。
第三种情况:
当millisLeft足够时,计算出当前准备调用onTick方法的时间lastTickStart,接着调用onTick方法。
onTick方法是同步的,执行该方法消耗的时间也需要计时。
于是第24行计算出理论上下一次回调onTick方法的剩余时间delay。
当onTick方法的耗时超过1个间隔时间时,就需要略过1次onTick方法回调。
于是第28行循环计算delay,直至正数,方才合理。
最后延迟millisLeft用mHandler发出消息,届时将再次进入handleMessage方法,成为3种情况中的一种。

源码巧妙地利用sendMessageDelayed方法在一个线程中实现了倒计时功能,又不会造成该线程的阻塞。
因为mHandler是在实例化倒计时对象时赋值的,所以要注意如果onTick和onFinish中有UI操作,实例化对象就必须在主线程完成。

停止倒计时也很简单,直接调用cancel方法:

   /**
     * Cancel the countdown.
     */
    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

该方法中直接将消息从消息队列中移除,该线程的Looper也就获取不到倒计时消息,从而达到停止的效果。

总结:
经过以上分析,可以知道倒计时可能有以下几种过程:
1. start马上–>onFinish,刚要开始,就要停止。
2. start延迟–>onFinish,开始一段时间后便停止。
3. start–>N个onTick–>onFinish,开始后,经历N个onTick方法,最后进入onFinish方法。

双目相机标定理论与编程实现 双目相机标定是计算机视觉中的重要任务,通过确定双目相机的内参和外参,可以实现立体视觉的深度感知和三维重建。通过使用OpenCV库提供的函数,我们可以方便地进行双目相机的标定工作。双目相机标定是计算机视觉中的重要任务,用于确定双目相机的内参和外参,以实现立体视觉的深度感知和三维重建。通过上述代码,我们可以获得左右相机的内参矩阵、畸变系数、旋转矩阵和平移矩阵等参数,从而完成双目相机的标定过程。使用双目相机采集一系列左右相机的图像,确保标定板在不同位置和角度下都能被双目相机拍摄到。函数来检测标定板的角点。 阅读详情

相关推荐

如何在 Ubuntu 24.04 或 22.04 上安装和使用 GDebi

本文介绍了在Ubuntu 24.04上安装和使用GDebi的方法。GDebi是DPKG的轻量级替代品,能够自动解析并安装.deb包的依赖项。文章详细说明了系统更新、安装GDebi的步骤,并演示了通过GUI和CLI两种方式安装.deb包的操作流程。此外,还提供了验证安装和卸载包的方法。GDebi虽然非必需,但为用户提供了处理依赖项的另一种选择,适合需要安装本地Debian包的用户。

山岚的运维笔记 1989

CountDownTimer 倒计时器

CountDownTimer倒计时器 计划一个倒计时,直到未来的某个时间,并定期通知 //30000–从调用start()到倒计时结束并调用onFinish()的未来毫秒数。1000–接收onTick(长)回调的时间间隔。 new CountDownTimer(30000, 1000) { public void onTick(long millisUntilFinished) { mTextField.setText("seconds remaining...

时代我西的博客 776

【医学影像】Deep Learning for Automatic Pneumonia Detection

写在前面的话: 这篇论文是北美放射学会(RSNA)在Kaggle平台上托管的肺炎区域检测挑战赛取得第二名成绩的解决方案。因为笔者需要用到其中的图像增强方案,因此本篇博客只介绍了数据集和图像增强,关于模型的改进和其它改进点没有涉及。 论文地址:https://arxiv.org/abs/2005.13899 代码地址:https://github.com/tatigabru/kaggle-rsna 比赛地址:https://www.kaggle.com/c/rsna-pneumonia-detection-c

chenzhoujian_的博客 1567

countDownTimer = new CountDownTimer(timerInMilliSecond+200,1000) { 导致的内存泄露怎么解决?

提供stopCountdown()方法:在Activity或Fragment的生命周期方法(如onPause()、onStop()或onDestroy())中调用此方法,确保在用户离开当前界面或组件销毁时及时取消计时器并释放引用。在本示例中,我们在onDestroy()中调用stopCountdown()以确保在销毁时清理计时器。在CountDownTimer的onFinish()回调中释放引用:当计时器完成计时后,将其引用设置为null,使计时器不再持有上下文的强引用,允许垃圾收集器适时回收上下文。

chezabo6116的博客 642

LinuxMint 22.1(Ubuntu24.04)下通过Wine完美运行同花顺远航版的实战指南

本文详细介绍了在LinuxMint 22.1(Ubuntu24.04)系统下通过Wine完美运行同花顺远航版的实战指南。从基础环境准备到深度优化,包括Wine环境配置、同花顺远航版安装、字体显示调优、任务栏兼容性修复等关键步骤,帮助Linux用户高效使用同花顺远航版进行股票交易和行情分析。

weixin_30919429的博客 571

大话西游2单机版V8一键架设教程:从下载到GM权限全流程(附仙玉修改技巧)

本文详细讲解了大话西游2单机版V8的一键架设全流程,包括环境准备、服务端配置、客户端安装及GM权限获取等关键步骤。特别提供了仙玉修改技巧和高级资源管理方法,帮助玩家快速搭建个性化游戏环境并掌握核心控制功能。教程涵盖Windows系统兼容性设置、常见问题解决方案以及数据备份策略,适合各类怀旧玩家和技术爱好者。

weixin_29254673的博客 1039

【Android】CountDownTimer的使用

最后,我们使用CountDownTimer实现了倒计时功能,并在onTick方法中更新了倒计时文本的内容。这样,就实现了根据给定的包名显示应用图标和倒计时的功能。在onTick方法中,可以更新UI上的倒计时时间,而在onFinish方法中,可以执行倒计时结束后的操作。在上述示例中,我们使用了一个单例对象来表示倒计时器,这样我们就可以在任何地方启动倒计时,而不用担心多次创建倒计时器的问题。在onTick方法中,我们更新了UI上的倒计时剩余时间,而在onFinish方法中,我们更新了UI上的提示信息。

aaajj的专栏 2748

半导体工厂自动化实战:用secs4net实现设备与MES系统通信(附完整代码)

本文详细介绍了如何利用secs4net框架实现半导体工厂设备与MES系统的高效通信。通过解析SECS/GEM协议的核心架构、关键业务场景实现及性能优化实践,帮助开发者快速掌握工业自动化通信技术,提升生产效率和系统稳定性。

transformer2023的博客 892

CountDownTimer使用心得及总结

一、概述项目中经常用到倒计时的功能,比如说限时抢购,手机获取验证码等等。而google官方也帮我们封装好了一个类:CountDownTimer,使我们的开发更加方便;二、APICountDownTimer是一个抽象类,有两个抽象方法,它的API很简单public abstract void onTick(long millisUntilFinished);//这个是每次间隔指定时间的回调,mill...

weixin_42564441的博客 4万+

大型我的世界RPG服务器开服全攻略:从环境配置到插件部署

搭建一个能支撑百人稳定在线的我的世界服务器,远不止选择服务端和安装插件那么简单。服务器架设涉及硬件选型、Java环境、端口放行、启动脚本与systemd守护等基础环节,而大型RPG玩法还依赖MythicMobs、Quests、LuckPerms等插件协同工作。理解这些技术组件的原理与配置逻辑,是确保长线运营的关键。对于希望打造原创剧情、职业副本和自定义Boss的团队而言,合理规划MySQL数据库、RCON批量管理及性能调优,能显著降低后期维护成本。本文围绕RPG服务器核心能力,从环境准备到插件部署,再到常见

weixin_27230891的博客 370

将Python爬取的数据导入钉钉多维表

摘要:本文介绍将Python爬取的数据导入钉钉多维表的完整解决方案。首先通过requests库爬取数据并解析为结构化格式,然后使用钉钉开放平台API对接多维表。关键步骤包括获取app_key、app_secret等凭证,通过OAuth2获取access_token,以及批量写入记录。文章详细说明了参数获取位置、字段类型匹配、权限配置等注意事项,并提供了错误处理建议和性能优化方法。适用于需要将网络数据同步到钉钉多维表的开发场景。

IT深耕十余载,大道之简 2131

Android支持暂停的CountDownTimer倒计时工具类

支持暂停,继续,修复总时长的倒计时, 由CountDownTimer实现的

zmlovelx(帅得不敢出门 程序员群31843264) 2225

英飞凌 TC4X MCAL之SPI中断与DMA高效传输实战

本文详细介绍了英飞凌TC4X芯片的SPI通信实战,重点讲解如何通过MCAL配置SPI中断与DMA实现高效数据传输。针对汽车电子领域的高吞吐需求,提供了从基础配置到中断处理、DMA优化的完整解决方案,包含代码示例和调试技巧,帮助开发者提升系统性能与CPU利用率。

k0l1m2n3o的博客 875

SwiftyPickerPopover 避坑指南:iOS 9 兼容、循环引用等 6 大常见问题全解析

SwiftyPickerPopover 是一款能在 iPhone / iPad(iOS 9+)上以弹窗形式展示内置选择器的开源 Swift 库,几行代码即可弹出字符串选择器、日期选择器、倒计时选择器和多列选择器。然而很多新手在接入 SwiftyPickerPopover 时,都会遇到循环引用导致的内存泄漏、iOS 9 上按钮消失、选择器行号错位等"隐形坑"。本文结合源码逐一拆解 6 大高频问题及解

gitblog_00820的博客 326

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

android的CountDownTimer开始时间不准或者不能倒计时到0的一种解决思路

我们需要用到android的CountDownTimer开始时间不准或者不能倒计时到0的一种解决思路

菜鸟江涛的博客 1万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

倒计时、定时器的七种方式,有这篇就够了

倒计时、定时器的使用次数也不少,这篇文章做一个总结,不用每次需要的时候到处去百度了,本文章内的代码都经过本人亲测有效!

As_thin的博客 3268

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

java countdowntimer_CountDownTimer 实现倒计时功能

CountDownTimerCountDownTimer 是android 自带的一个倒计时类,使用这个类可以很简单的实现 倒计时功能CountDownTimer 的实现方式new CountDownTimer(6000,1000) {//第一个参数表示的是倒计时的总时间,第二参数表示的是倒计时的间隔时间。@Overridepublic void onTick(long millisUntilFi...

weixin_31310737的博客 1173

安卓倒计时方案实现经验案例

基于CountDownTimer的Android倒计时方案实现

ningmengjiang3的博客 1527

Android基础之——CountDownTimer类,轻松实现倒计时功能

在发现这个类之前,一直是用的handler,子线程发消息,UI线程进行倒计时的显示工作。前几天在做一个倒计时显示的时候发现了这个类,用起来很方便 翻看了下源码,内部已经帮我们实现了handler的子线程操作

Micheal_Yang's Blog 2709

CountDownTimer使用

CountDownTimer

知识共享,你我皆是知识的搬运工 9624

安卓项目实战之:倒计时类CountDownTimer的使用详解

前言 在Android应用中几乎都能看到,闪屏页或者欢迎页右上角有一个 “倒计时 + 跳过” 的功能,还有就是获得验证码的倒计时功能,Android 实现倒计时的方式有多种,Handler 延时发送 Message,Timer 和 TimerTask 配合使用,使用 CountDownTimer 类等。相比而言,经过系统封装的 CountDownTimer 算是使用起来最为方便的方式之一。 Cou...

智玲君 2065

CountDownTimer用法

Section1   new CountDownTimer(10000, 1000) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { } }.start(); 看源码解

perfectnihil的博客 395

Android 倒计时——Timer和CountDownTimer的使用,实现启动,暂停,继续,重复,重设时长以及启动service后台倒计时

实现效果 单个倒计时功能 列表倒计时功能 自定义倒计时类 public class CountDownTimerSupport implements ITimerSupport { private Timer mTimer; private Handler mHandler; /** * ...

meixi_android的博客 5525

CountDownTimer官方介绍和使用

CountDownTimer官方翻译

linxingqianglai的专栏 2303

CountDownTimer倒计时器的使用

private TextView vertifyView; private CountDownTimer timer = new CountDownTimer(10000, 1000) { @Override public void onTick(long millisUntilFinished) { vertifyView.setText((millisUntilFinished

approche的专栏 812

CountDownTimer的简单使用

需求:加载某一个界面,在页面中待5秒后再关闭 效果图如下: 设置了一个点击事件,当文字显示为Skip activity时,点击跳转界面。 代码及介绍如下图: 核心功能代码如下 Android自带的CountDownTimer这个工具类,也是通过Handler和子线程来实现的。 //倒计时工具类CountDownTimer //CountDownTimer的构造方法有两个参数...

计蒙不吃鱼的博客 3375
上一篇: JsonDeserializer——Gson自定义解析类型错误的字段
下一篇: 【源码分析】走进EventBus
binaryshao
博客等级 码龄11年 52粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值