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

Kotlin Android倒计时视图开发:解决代码崩溃问题并实现可动态修改的倒计时器

Fixing Your Android Countdown Crash & Adding Dynamic Timer Updates

Hey there! Let's break down why your countdown code is crashing and get it working properly—plus add the ability to dynamically update the timer value whenever you need.

First, Why Your Current Code Is Crashing

Your while (timer > 1) loop runs synchronously on the main thread, and it doesn't wait for the postDelayed to finish before iterating again. That means in a split second, it creates hundreds of delayed tasks all scheduled to run 1 second later. This overwhelms the main thread, causes UI jank, and eventually leads to the crash you're seeing (the Signal Catcher log is a sign the system is trying to handle the overloaded thread).

On top of that, your global timer variable is being modified by all those delayed tasks at once, leading to inconsistent UI updates and race conditions.

Here's the Correct Implementation

The best way to handle countdowns in Android is using the built-in CountDownTimer class—it's designed for this exact use case, manages the timing correctly, and avoids thread issues.

Step 1: Declare a CountDownTimer Variable

First, add this variable to your Activity/Fragment (you can keep your global timer for sync if needed):

private var countDownTimer: CountDownTimer? = null
var timer: Int = 50 // Keep your global variable if you need it elsewhere

Step 2: Create a Proper Countdown Function

Replace your existing timer() function with this:

private fun startCountdown(initialSeconds: Int) {
    // Cancel any existing timer first to avoid overlapping countdowns
    countDownTimer?.cancel()

    countDownTimer = object : CountDownTimer((initialSeconds * 1000).toLong(), 1000) {
        override fun onTick(millisUntilFinished: Long) {
            val remainingSeconds = (millisUntilFinished / 1000).toInt()
            timer_text.text = remainingSeconds.toString()
            // Sync the global timer variable if you need it elsewhere
            timer = remainingSeconds
        }

        override fun onFinish() {
            timer_text.text = "0"
            timer = 0
            // Add any end-of-countdown logic here (e.g., show a completion message)
        }
    }.start()
}

Step 3: Add Dynamic Update Support

To change the timer value on the fly (e.g., set it to 30 mid-countdown), just call this function:

fun updateCountdown(newSeconds: Int) {
    timer = newSeconds
    startCountdown(newSeconds)
}

Step 4: Clean Up to Avoid Memory Leaks

Always cancel the timer when your Activity/Fragment is destroyed to prevent memory leaks:

override fun onDestroy() {
    super.onDestroy()
    countDownTimer?.cancel()
}

How to Use It

  • Start the initial countdown with startCountdown(timer) (since your global timer is 50, this will start at 50)
  • Whenever you need to change the timer value, call updateCountdown(30) (or any number you want)

Your Original Code & Logs for Reference

Global declaration:

var timer: Int = 50 // Declared globally

Original countdown function:

private fun timer(){
    timer_text.text = timer.toString() // Text view in UI
    while (timer > 1){
        Handler().postDelayed({
            timer--
            timer_text.text = timer.toString() // Update the Text view in UI
        }, 1000)
    }
}

Logcat output:

I/sandaru.projec: Thread[6,tid=11100,WaitingInMainSignalCatcherLoop,Thread*=0xb400007b3dcd9f50,peer=0x13280238,"Signal Catcher"]: reacting to signal 3
I/sandaru.projec: 
I/sandaru.projec: Wrote stack traces to tombstoned
D/EGL_emulation: app_time_stats: avg=5.51ms min=1.98ms max=10.47ms count=60

内容的提问来源于stack exchange,提问作者Sandaru Fernando

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 16:02:37