Android实现倒计时的几种方案
前言
关于倒计时可以说我们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中销毁资源哦。
如有错漏还望指出,如有更多或更好的方法,也可以在评论区交流讨论。
如果感觉本文对你有一点点点的启发,还望你能点赞
支持一下,你的支持是我最大的动力。
Ok,这一期就此完结。
————————————————
原文链接:https://juejin.cn/post/7128947531471388709
Android实现倒计时的几种方案相关推荐
- 实现倒计时的几种方案汇总
前言 关于倒计时可以说我们App开发中常见的一种场景了,比如Splash倒计时跳转首页,比如发送短信之后倒计时60秒显示等等. 关于倒计时的实现方式,大家可能有不同的做法,这里做一下总结看看你使用的是 ...
- Android阴影实现的几种方案
作者:newki 链接: https://juejin.cn/post/7149706291261210654 圆角容器?自定义圆角容器?自定义圆角加阴影容器? 太难了,不知道大家有没有同款UI设计师 ...
- Android性能优化的5种方案
指标 量化性能的指标有很多,但最重要的就是以下5种: 包大小 响应时间 内存 CPU 耗电量 优化性能就是可以从以上5点入手. 包大小优化 顾名思义就是减少apk包体积大小,apk大小主要取决于res ...
- Android TextView滚动的两种方案
方案有两个 1使用Android原生TextView,优点是简单,缺点是一旦失去焦点,就无法滚动了. 2自定义TextView,缺点是稍微麻烦点,优点是可以一直滚动. 方案1 使用Android原生T ...
- Android设置壁纸的几种方案
Android设置壁纸有许多方法,主要思路有两种: 1:通过WallpaperManager设置 2:通过系统程序设置 下文将分开说明: <1>通过WallpaperManager设置 该 ...
- android 屏幕录制方案,Android录屏的三种方案
本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...
- Android 屏幕适配的一种方案
转载请标明出处: http://blog.csdn.net/xuehuayous/article/details/51671937 本文出自:[Kevin.zhou的博客] 前言:在<Andro ...
- Android音频录制方案,Android录屏的三种方案
本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...
- Android 添加微信分享三种实现方案
Android 添加微信分享三种方案 使用android的intent实现应用程序之间的通信,将信息通过intent传递给微信.这种方式的局限性在于 a.只能发送图片,而不是文字或者图片+文字. b. ...
最新文章
- Java基础之移位运算,为什么高位补1?
- 文件系统与NoSQL分布式存储技术对比
- Android6.0 wakelock深入分析
- Python地图可视化三大秘密武器
- JavaOne 2014 –有关提交的一些初步分析
- mysql中起飞到达城市查询_让mysql慢慢起飞 - 初识慢日志
- 人工智能芯片与传统芯片的区别
- linux man 手册翻译,close (linux man) 翻译
- 去掉iframe的水平滚动条而保留垂直滚动条
- 创业者如何利用数字经济实现企业升级?
- 基于阿里云实现简单的语音识别功能
- ext源码阅读 - DomHelper - createHtml,insertHtml
- 分布式文件系统(FastDFS+Tengine+fastdfs-nginx-module)
- 电气工程师需掌握哪些计算机知识,一名合格电气工程师必须掌握的10个基本技能...
- ERP项目组成员及各项目组职责
- 机器人油封_机器人油封 机器人减速机 机器人伺服电机油封 KVNOK油封
- jenkins+svn+脚本实现CIDI
- C++中string类下的begin,end,rbegin,rend的用法
- 深度学习(二)——从零自己制作数据集到利用deepNN实现夸张人脸表情的实时监测(tensorflow实现)
- 使用 Python 脚本执行国密 sm2 加解密
热门文章
- 宿舍管理小程序开发制作功能介绍
- fastadmin操作中添加自定义按钮,点击弹出表格
- 面试题 请简述vue双向数据绑定原理
- java web工程搭建_手把手搭建javaweb项目_手把手javaweb
- Leecode:给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数
- 【excel导出两级表头实现】
- 小白知识:什么是云计算?
- 静态内部类的单例模式如何保证线程安全
- 推荐3个Python 文本终端 GUI 框架,太酷了
- NPOI Excel数据写入及读取