当前位置: 首页 > news >正文

Android 倒计时总结

文章目录

  • Android 倒计时总结
    • Handler方案
    • CountDownTimer方案
    • Timer方案
    • Flow方案
    • 总结
    • 源码下载

Android 倒计时总结

Handler方案

class MyHandler(private val intervalTime: Long, // 间隔private val totalTime: Long, // 总时长onTick: (Long) -> Unit, // 每秒回调onFinish: () -> Unit // 结束回调
) {private var runType = RunType.INITprivate var handler: Handler? = Handler(Looper.getMainLooper())private val weekOnTick = WeakReference(onTick)private val weekOnFinish = WeakReference(onFinish)private var currentTime = 0Lprivate val runnable = object : Runnable {override fun run() {if (currentTime > 0) {// 进行中currentTime -= intervalTimeweekOnTick.get()?.invoke(currentTime)handler?.postDelayed(this, intervalTime)} else {// 结束weekOnFinish.get()?.invoke()runType = RunType.STOP}}}fun start() {if (runType == RunType.RUNNING) returnrunType = RunType.RUNNINGif (currentTime == 0L) {currentTime = totalTime}handler?.post(runnable)}fun pause() {if (runType != RunType.RUNNING) returnrunType = RunType.PAUSEhandler?.removeCallbacksAndMessages(null)}fun stop() {runType = RunType.STOPhandler?.removeCallbacksAndMessages(null)currentTime = 0weekOnFinish.get()?.invoke()}fun release() {runType = RunType.INIThandler?.removeCallbacksAndMessages(null)handler = nullweekOnTick.clear()weekOnFinish.clear()}enum class RunType {INIT, RUNNING, PAUSE, STOP}
}

使用:

class HandlerFragment : BaseFragment() {private lateinit var tvCountDown: TextViewprivate lateinit var btnStart: Buttonprivate lateinit var btnPause: Buttonprivate lateinit var btnStop: Buttoncompanion object {@JvmStaticfun newInstance() = HandlerFragment()}private lateinit var myHandler: MyHandleroverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View {return inflater.inflate(R.layout.fragment_handler, container, false)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)tvCountDown = view.findViewById(R.id.tv_count_down)btnStart = view.findViewById(R.id.btn_start)btnPause = view.findViewById(R.id.btn_pause)btnStop = view.findViewById(R.id.btn_stop)myHandler = MyHandler(1000L, 10_000L, { time ->tvCountDown.text = "剩余时间:${time / 1000}s"}, {tvCountDown.text = "倒计时结束!"})btnStart.setOnClickListener {myHandler.start()}btnPause.setOnClickListener {myHandler.pause()}btnStop.setOnClickListener {myHandler.stop()}}override fun onDestroyView() {super.onDestroyView()myHandler.release()}}

CountDownTimer方案

class MyCountDownTimer(private val intervalTime: Long,private val totalTime: Long,onTick: (Long) -> Unit,onFinish: () -> Unit
) {private var runType = RunType.INITprivate val weekOnTick = WeakReference(onTick)private val weekOnFinish = WeakReference(onFinish)private var countDownTimer: CountDownTimer? = nullfun start() {if (runType == RunType.RUNNING) returnrunType = RunType.RUNNINGcountDownTimer = object : CountDownTimer(totalTime, intervalTime) {override fun onTick(p0: Long) {weekOnTick.get()?.invoke(p0)}override fun onFinish() {weekOnFinish.get()?.invoke()runType = RunType.STOP}}countDownTimer!!.start()}fun stop() {runType = RunType.STOPcountDownTimer?.cancel()weekOnFinish.get()?.invoke()}fun release() {countDownTimer?.cancel()countDownTimer = nullweekOnTick.clear()weekOnFinish.clear()}enum class RunType {INIT, RUNNING, STOP}
}

使用:

class CountDownTimerFragment : BaseFragment() {private lateinit var tvCountDown: TextViewprivate lateinit var btnStart: Buttonprivate lateinit var btnStop: Buttonprivate lateinit var countDownTimer: MyCountDownTimercompanion object {@JvmStaticfun newInstance() = CountDownTimerFragment()}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View {return inflater.inflate(R.layout.fragment_countdown_timer, container, false)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)tvCountDown = view.findViewById(R.id.tv_count_down)btnStart = view.findViewById(R.id.btn_start)btnStop = view.findViewById(R.id.btn_stop)countDownTimer = MyCountDownTimer(1000L, 10_000L,{ time ->tvCountDown.text = "剩余时间:${time / 1000}s"},{tvCountDown.text = "倒计时结束!"})btnStart.setOnClickListener {countDownTimer.start()}btnStop.setOnClickListener {countDownTimer.stop()}}override fun onDestroyView() {super.onDestroyView()countDownTimer.release()}
}

Timer方案

class MyTimer(private val intervalTime: Long,private val totalTime: Long,onTick: (Long) -> Unit,onFinish: () -> Unit
) {private val mainHandler = Handler(Looper.getMainLooper())private var runType = RunType.INITprivate val weekOnTick = WeakReference(onTick)private val weekOnFinish = WeakReference(onFinish)private var timer: Timer? = nullprivate var currentTime = 0Lfun start() {if (runType == RunType.RUNNING) returnrunType = RunType.RUNNINGcurrentTime = totalTimetimer = Timer()timer!!.schedule(object : TimerTask() {override fun run() {if (currentTime <= 0) {mainHandler.post {weekOnFinish.get()?.invoke()}cancel()runType = RunType.STOP} else {currentTime -= intervalTimemainHandler.post {weekOnTick.get()?.invoke(currentTime)}}}}, 0, intervalTime)}fun stop() {if (runType != RunType.RUNNING) returnrunType = RunType.STOPtimer?.cancel()weekOnFinish.get()?.invoke()}fun release() {timer?.cancel()timer = nullweekOnTick.clear()weekOnFinish.clear()}enum class RunType {INIT, RUNNING, STOP}
}

使用:

class TimerFragment : BaseFragment() {private lateinit var tvCountDown: TextViewprivate lateinit var btnStart: Buttonprivate lateinit var btnStop: Buttonprivate lateinit var myTimer: MyTimercompanion object {@JvmStaticfun newInstance() = TimerFragment()}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View {return inflater.inflate(R.layout.fragment_timer, container, false)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)tvCountDown = view.findViewById(R.id.tv_count_down)btnStart = view.findViewById(R.id.btn_start)btnStop = view.findViewById(R.id.btn_stop)myTimer = MyTimer(1000L, 10_000L,{ time ->tvCountDown.text = "剩余时间:${time / 1000}s"},{tvCountDown.text = "倒计时结束!"})btnStart.setOnClickListener {myTimer.start()}btnStop.setOnClickListener {myTimer.stop()}}override fun onDestroyView() {super.onDestroyView()myTimer.release()}
}

Flow方案

class MyFlow(private val intervalTime: Long,private val totalTime: Long,private val onTick: (Long) -> Unit,private val onFinish: () -> Unit,private val scope: CoroutineScope
) {private var runType = RunType.INITprivate val weekOnTick = WeakReference(onTick)private val weekOnFinish = WeakReference(onFinish)private var job: Job? = nullprivate var currentTime = 0Lfun start() {if (runType == RunType.RUNNING) returnrunType = RunType.RUNNINGjob = scope.launch {flow {currentTime = totalTimewhile (currentTime >= 0) {emit(currentTime)delay(intervalTime)currentTime -= 1000}}.collect {weekOnTick.get()?.invoke(it)if (it <= 0) {weekOnFinish.get()?.invoke()runType = RunType.STOP}}}}fun stop() {if (runType != RunType.RUNNING) returnrunType = RunType.STOPjob?.cancel()weekOnFinish.get()?.invoke()}fun release() {job?.cancel()job = nullweekOnTick.clear()weekOnFinish.clear()}enum class RunType {INIT, RUNNING, STOP}
}

使用:

class FlowFragment : BaseFragment() {private lateinit var tvCountDown: TextViewprivate lateinit var btnStart: Buttonprivate lateinit var btnStop: Buttonprivate lateinit var myFlow: MyFlowcompanion object {@JvmStaticfun newInstance() = FlowFragment()}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View {return inflater.inflate(R.layout.fragment_flow, container, false)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)tvCountDown = view.findViewById(R.id.tv_count_down)btnStart = view.findViewById(R.id.btn_start)btnStop = view.findViewById(R.id.btn_stop)myFlow = MyFlow(1000L, 10_000L,{ time ->tvCountDown.text = "剩余时间:${time / 1000}s"},{tvCountDown.text = "倒计时结束!"},lifecycleScope)btnStart.setOnClickListener {myFlow.start()}btnStop.setOnClickListener {myFlow.stop()}}override fun onDestroyView() {super.onDestroyView()myFlow.release()}
}

总结

  • 简单需求:优先选用CountDownTimer,避免重复造轮子

  • 界面交互:使用Handler时注意与View的生命周期绑定

  • 后台任务:Timer方案需配合Service使用

  • 新项目推荐:采用Kotlin Flow实现,搭配协程更高效

  • 性能关键:避免在倒计时回调中执行耗时操作

  • 内存优化:所有方案都需注意释放资源

源码下载

相关文章:

  • SmolDocling-256M:极小参数量的视觉语言模型|端到端文档解析方案的另一种思路
  • 80x86CPU入栈与出栈操作
  • 软考-系统架构设计师-第十章 系统质量属性和架构评估
  • 系统安装出现的问题 老毛桃
  • 算法训练第二天
  • FEMFAT许可的有效期限
  • “谁能进,谁不能进?”——用NAC精准控制网络访问
  • 痉挛性斜颈的健康护理要点:从日常管理到康复辅助
  • CSS--background-repeat详解
  • 【第4章 图像与视频】4.4 离屏 canvas
  • 手机实名认证接口如何用C#进行调用?
  • Linux环境下多进程Socket通信实现
  • 学习路之PHP--easyswoole操作数据库
  • 性能测试工具选型指南
  • UNICEODE_STRING
  • 【Markdown基础语法】
  • Oracle/openGauss中,DATE/TIMESTAMP与数字日期/字符日期比较
  • 黑马点评项目02——商户查询缓存(缓存穿透、缓存雪崩、缓存击穿)以及细节
  • 解析C++排序算法
  • vue-seamless-scroll 结束从头开始,加延时后滚动
  • 网站建设测试流程/百度收录在线提交
  • 班级网站建设php/做网站公司哪家比较好
  • 自己做的网站会被黑吗/重庆seo整站优化
  • 网站运营怎么自学/seo有哪些作用
  • 如何用wget下载WordPress/优化关键词快速排名
  • 长沙口碑好网站建设企业/百度扫一扫