前言

关于倒计时可以说我们App开发中常见的一种场景了,比如Splash倒计时跳转首页,比如发送短信之后倒计时60秒显示等等。

关于倒计时的实现方式,大家可能有不同的做法,这里做一下总结看看你使用的是哪一种呢?

一、CountDownTimer的实现

直接上代码

      //倒计时的方式一fun countDownTimer() {var num = 60timer = object : CountDownTimer((num + 1) * 1000L, 1000L) {override fun onTick(millisUntilFinished: Long) {YYLogUtils.w("当时计数:" + num)if (num == 0) {YYLogUtils.w("重新开始")num = 60} else {num--}}override fun onFinish() {YYLogUtils.w("倒计时结束了..." + num)}}timer?.start()}private var timer: CountDownTimer? = nulloverride fun onDestroy() {super.onDestroy()timer?.cancel()}复制代码

没什么花活,就是android.os包下面的 CountDownTimer 类的使用。内部实现使用了 Handler 进行封装。

二、直接用Handler的实现

    private var handlerNum = 60private val mHandler = object : Handler(Looper.getMainLooper()) {override fun handleMessage(msg: Message) {when (msg.what) {1 -> {if (handlerNum > 0) {handlerNum--YYLogUtils.w("当时计数:" + handlerNum)countDownHander()} else {stopCountDownHander()}}}}}override fun onDestroy() {super.onDestroy()stopCountDownHander()}fun countDownHander() {mHandler.sendEmptyMessageDelayed(1, 1000)}fun stopCountDownHander() {mHandler.removeCallbacksAndMessages(null)}复制代码

我们可以直接使用Handler的延时发送消息实现倒计时。

当然另一种做法是使用 Runnable 来实现。


Handler handler = new Handler();Runnable runnable = new Runnable() {@Overridepublic void run() {recLen++;txtView.setText("" + recLen);handler.postDelayed(this, 1000);}public void test(){handler.postDelayed(runnable, 1000);
}复制代码

三、直接用Time、TimeTask的实现

以上是Android的倒计时方案,其实Java的Api也是支持倒计时实现的,比如 Timer 配合 TimerTask 就可以实现简单的倒计时。

fun countDownTimer2() {var num = 60val timer = Timer()val timeTask = object : TimerTask() {override fun run() {num--YYLogUtils.w("当时计数:" + num)if (num < 0) {timer.cancel()}}}timer.schedule(timeTask, 1000, 1000)}复制代码

四、使用Theard倒计时

我们可以通过Thread的sleep方法来实现倒计时,不过由于是子线程我们不能更新UI,所以还是需要配合Handler实现。

    private var mThread: Thread = Thread(this)private var mflag = falseprivate var mThreadNum = 60override fun run() {while (mflag && mThreadNum >= 0) {try {Thread.sleep(1000)} catch (e: InterruptedException) {e.printStackTrace()}val message = Message.obtain()message.what = 1message.arg1 = mThreadNumhandler.sendMessage(message)mThreadNum--}}private val handler = Handler(Looper.getMainLooper()) { msg ->if (msg.what == 1) {val num = msg.arg1//由于需要主线程显示UI,这里使用Handler通信YYLogUtils.w("当时计数:" + num)}true}//开启倒计时fun countDownThread() {if (!mThread.isAlive) {mflag = trueif (mThread.state == Thread.State.TERMINATED) {mThread = Thread(this@DemoCountDwonActivity)if (mThreadNum == -1) mThreadNum = 60mThread.start()} else {mThread.start()}} else {mflag = false}}override fun onDestroy() {super.onDestroy()mflag = false}
复制代码

这里的销毁线程我没有使用stop方法,已经不推荐我们使用,我们使用flag来判断即可。

五、使用框架RxJava

这样的线程并不是我们想要的,我们通常并不会直接new Thread 来进行一些逻辑操作,比如我们可能使用RxJava框架,通过操作符的方式来进行倒计时。

比我们倒计时4秒之后跳转页面的实现:

val SHOTDOWN_TIME = 4val mDisposables : Disposable? = nullObservable.interval(0, 1, TimeUnit.SECONDS).take(SHOTDOWN_TIME.toLong()).map {return@map SHOTDOWN_TIME - it}.observeOn(AndroidSchedulers.mainThread()).subscribe({LogUtil.e(it.toString())}, {it.printStackTrace()}, {checkJump()}, {mDisposable = it})override fun onDestroy() {super.onDestroy()mDisposable?.dispose()}复制代码

注意我们还是需要通过mDisposable对象在页面销毁的时候释放,以免内存泄露,有没有简单一点方式?

六、Kotlin Flow 的实现

上面的方法都需要销毁资源,好麻烦,能不能自动取消?协程不就行了。

是的 lifecycleScope 根据生命周期自动取消的协程作用域,配合Flow的操作符完成倒计时岂不是完美。

好吧,你是自动倒计时了。结束之后取消协程,销毁也能取消协程,那如果我想手动的取消倒计时怎么办?比如倒计时60秒我就要在第50秒的时候强制取消协程怎么办?

launch方法返回的不就是Job 对象吗?根据此上下文对象不就可以取消协程了吗?

看看灵活的Flow倒计时如何实现。

定义一个扩展方法:


/*** 倒计时的实现*/
@ExperimentalCoroutinesApi
fun FragmentActivity.countDown(time: Int = 5,start: (scop: CoroutineScope) -> Unit,end: () -> Unit,next: (time: Int) -> Unit
) {lifecycleScope.launch {// 在这个范围内启动的协程会在Lifecycle被销毁的时候自动取消flow {(time downTo 0).forEach {delay(1000)emit(it)}}.onStart {// 倒计时开始 ,在这里可以让Button 禁止点击状态start(this@launch)}.onCompletion {// 倒计时结束 ,在这里可以让Button 恢复点击状态end()}.catch {//错误YYLogUtils.e(it.message ?: "Unkown Error")}.collect {// 在这里 更新值来显示到UInext(it)}}
}复制代码

使用:

     fun startCountDown() {var timeDownScope: CoroutineScope? = nullcountDown(time = 60,start = {timeDownScope = itYYLogUtils.e("开始")},end = {YYLogUtils.e("结速倒计时")toast("结速倒计时")},next = {YYLogUtils.w("当时计数:" + it)if (it == 50) {timeDownScope?.cancel()}})}
复制代码

无需onDestory中销毁资源,如果想自由手动的控制倒计时,我们再start的高阶函数中接收父协程的上下文对象即可自动控制。使用起来也是超级简单。

总结

倒计时的实现是我们常用的功能,如果你的项目是Kotlin构建的,那么我建议使用Flow来实现这种功能,使用扩展函数进行封装,使用起来更加的简单。

如果你们项目是Java语言实现的,那么同样的可以选择一种方式进行一个工具类的封装,也能达到同样的效果,只是记得需要在onDestory中销毁资源哦。

作者:newki
链接:https://juejin.cn/post/7128947531471388709
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

实现倒计时的几种方案汇总相关推荐

  1. Android实现倒计时的几种方案

    前言 关于倒计时可以说我们App开发中常见的一种场景了,比如Splash倒计时跳转首页,比如发送短信之后倒计时60秒显示等等. 关于倒计时的实现方式,大家可能有不同的做法,这里做一下总结看看你使用的是 ...

  2. 【数据竞赛】2020 Kaggle 10大竞赛方案汇总

    作者: 尘沙黑夜 2020 Kaggle 10大竞赛方案汇总 1  2020kaggle精选10大赛事汇总 1.1  2019 Data Science Bowl(3493只队伍) 1.2  Tens ...

  3. Net Core下使用RabbitMQ比较完备两种方案(虽然代码有点惨淡,不过我会完善)

    一.前言     上篇说给大家来写C#和Java的方案,最近工作也比较忙,迟到了一些,我先给大家补上C#的方案. 二.使用的插件     HangFire 一个开源的.NET任务调度框架,最大特点在于 ...

  4. iOS活动倒计时的两种实现方式

    代码地址如下: http://www.demodashi.com/demo/11076.html 在做些活动界面或者限时验证码时, 经常会使用一些倒计时突出展现. 现提供两种方案: 一.使用NSTim ...

  5. 企业级BOM系统与外部系统集成的几种方案

    企业级的BOM体系在整车厂起到信息"脊椎"的作用,因而也被称为制造企业的DNA,是贯穿于企业业务始终的核心要素,可以抽象成企业级的系统,该系统既是支撑整车开发.制造过程的核心系统, ...

  6. 订单超时自动取消3种方案——我们用这种!

    大家好,大家对电商购物应该都比较熟悉了,我们应该注意到,在下单之后,通常会有一个倒计时,如果超过支付时间,订单就会被自动取消. 下单 今天,我们来聊聊订单超时未支付自动取消的几种方案. 1.定时任务 ...

  7. 【Web技术】948- 生成前端海报的 N 种方案和优劣

    一.背景 工作中做了很多生成海报的功能,不同需求,不同场景,使用了几种方案,各有优劣.一直想要整理一下,但这个过程中的思考和遇到的问题没有记录下来,比如图片的跨域问题,文字的问题,做完没有记录,无迹可 ...

  8. 【HTTP】989- HTTP 传输大文件的几种方案

    在 JavaScript 中如何实现大文件并发上传? 和 JavaScript 中如何实现大文件并行下载? 这两篇文章中,阿宝哥介绍了如何利用 async-pool 这个库来优化传输大文件的功能.本文 ...

  9. 常见的频率合成方案汇总

    常见的频率合成方案汇总 频率合成就是从一个高稳定度频率(来源可以是晶振等)出发,对其进行类似于数学的加减乘除操作得到一些自己需要的目标频率信号,经历了长久以来的不断发展,现在已经有了很多应用广泛的相关 ...

最新文章

  1. maven基础概念学习1
  2. 推荐8个可以显著提高工作效率的办公神器
  3. NAR:UNITE真菌鉴定ITS数据库——处理未分类和并行分类
  4. 连接svn认证失败有那些原因_windows局域网搭建svn服务器
  5. Android-滑动解锁高亮文字自定义TextView
  6. SAP CRM Enterprise Search 培训材料
  7. leetcode 1203. 项目管理(拓扑排序)
  8. OpenCL向量相加
  9. 四、Linux用户管理
  10. 第九章:Servlet工作原理解析
  11. MyCat 主键ID自增长配置
  12. BaseRecyclerViewAdapterHelper开源项目之BaseSectionQuickAdapter 实现Expandable And collapse效果的源码学习...
  13. App Store ASO必备指南:3个步骤做好aso优化
  14. 中微通用进销存软件 绿色软件联盟
  15. 华宇法律人工智能平台:用新一代的科技推动新时代的法律服务达到完全互联、无所不在 |百万人学AI评选
  16. R语言可视化探索BRFSS数据并逻辑回归Logistic回归预测中风
  17. 建立内部动态DNS服务器
  18. self.font = core.getfont(font, size, index, encoding, layout_engine=layout_engine) OSError: cannot o
  19. Oracle分区详解和创建,数据库优化-Oracle表分区的创建和分类
  20. 《2015》——王小波

热门文章

  1. matlab改consolas字体+微软雅黑的完美解决方法
  2. 算法—学习、练习和总结
  3. oracle安装报错ins-30131
  4. 2013计算机应用基础试题及答案,2013年电大计算机应用基础试题及参考答案
  5. Hololens 开发笔记(10)——World Anchor
  6. [译] 响应式脑电波—如何使用 RxJS、Angular、Web 蓝牙以及脑电波头戴设备来让我们的大脑做一些更酷的事...
  7. 关于短信验证码报错和解决问题
  8. html文件中如何写时间戳,复制文件时间戳
  9. LibreOJ #6177. 「美团 CodeM 初赛 Round B」送外卖2【状压DP】
  10. 数学建模入门 方法及代码