使用Timer().schedule()延迟执行方法导致应用崩溃问题排查
问题分析与解决方案
崩溃直接原因:非主线程操作UI组件
Android强制要求所有View的更新操作(如设置颜色、修改可见性)必须在主线程执行,你通过Timer().schedule()创建的任务会在后台线程运行,直接在回调里调用speed.setTextColor()、times.visibility = View.VISIBLE这类方法,会触发CalledFromWrongThreadException,导致应用崩溃。
代码中的其他逻辑问题
- 进度条动画无效:
while循环会瞬间将currentProgress从0递增到60,所有ObjectAnimator几乎同时启动,根本看不到进度逐步增长的动画效果。 - 进度判断时机不合理:循环结束后
currentProgress已固定为60,Timer延迟任务的判断逻辑虽能触发,但和进度动画的实际执行节奏完全脱节。
修复后的完整代码
改用Android主线程调度工具处理UI操作,同时重构进度条动画逻辑:
fun progressBarAnimation( progressBar: ProgressBar, speed: TextView, mph: TextView, timer: TextView, times: TextView, yellowTimesBar: View, recTime1: TextView, recTime2: TextView, recTime3: TextView ) { progressBar.max = 60 // 用ValueAnimator实现平滑的进度条动画 val progressAnimator = ValueAnimator.ofInt(0, progressBar.max) progressAnimator.duration = progressBar.max * 500L // 总时长与原逻辑保持一致 progressAnimator.addUpdateListener { animator -> val currentProgress = animator.animatedValue as Int progressBar.progress = currentProgress // 进度达到60时触发闪烁和时间记录显示 if (currentProgress == 60) { startFlashAnimation(speed, mph, timer) showTimeRecords(times, yellowTimesBar, recTime1) } } progressAnimator.start() } // 封装闪烁动画逻辑,确保在主线程执行 private fun startFlashAnimation(vararg views: TextView) { val handler = Handler(Looper.getMainLooper()) val colorYellow = Color.parseColor("#FFE222") val colorWhite = Color.parseColor("#FFFFFF") // 定义闪烁序列:黄-白循环3次 val flashSteps = listOf( colorYellow to 0L, colorWhite to 400L, colorYellow to 800L, colorWhite to 1200L, colorYellow to 1600L, colorWhite to 2000L ) flashSteps.forEach { (color, delay) -> handler.postDelayed({ views.forEach { it.setTextColor(color) } }, delay) } } // 显示时间记录组件,确保在主线程执行 private fun showTimeRecords( times: TextView, yellowTimesBar: View, recTime1: TextView ) { Handler(Looper.getMainLooper()).post { times.visibility = View.VISIBLE yellowTimesBar.visibility = View.VISIBLE recTime1.visibility = View.VISIBLE } }
关键修复点说明
- 主线程约束:通过
Handler(Looper.getMainLooper())将所有UI操作切换到主线程执行,彻底解决崩溃问题。 - 动画逻辑优化:用
ValueAnimator替代循环创建多个ObjectAnimator,实现真正的平滑进度增长,同时在动画过程中实时判断进度触发后续逻辑。 - 代码解耦:将闪烁、时间显示逻辑拆分为独立方法,提升代码可读性和可维护性。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

