You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:15:29