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

如何使用Kotlin实现Minute:Seconds:MILLISECONDS格式倒计时并支持macroseconds显示

Kotlin Countdown: MM:SS:mmm Format with Fast-Ticking Millisecond Display

Key Features Covered

  • Proper Minute:Seconds:Milliseconds formatting
  • Rapid millisecond updates (simulating microsecond-level ticking)
  • Clean, cancelable timer logic using Coroutines (no messy Handlers!)
  • Reusable code structure

Complete Implementation

First, let's create a reusable countdown manager (you can drop this into your project as a top-level class or inside your Activity/Fragment):

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class CountdownManager {
    private var countdownJob: Job? = null

    /**
     * Starts a countdown
     * @param totalSeconds Total duration of the countdown in seconds
     * @param onTick Called every 10ms with the formatted time string
     * @param onFinish Called when the countdown reaches zero
     */
    fun start(totalSeconds: Int, onTick: (String) -> Unit, onFinish: () -> Unit) {
        // Cancel any existing countdown to avoid duplicates
        countdownJob?.cancel()
        
        countdownJob = CoroutineScope(Dispatchers.Main).launch {
            var remainingMillis = totalSeconds * 1000L
            while (remainingMillis > 0) {
                onTick(formatTime(remainingMillis))
                // Delay 10ms instead of 1s to get that fast-ticking millisecond effect
                // This updates the display 100 times per second, making the millis jump rapidly
                delay(10)
                remainingMillis -= 10
            }
            // Final tick to show zero
            onTick(formatTime(0))
            onFinish()
        }
    }

    /**
     * Stops the current countdown if it's running
     */
    fun stop() {
        countdownJob?.cancel()
    }

    /**
     * Formats remaining milliseconds into MM:SS:mmm format
     * For the "10:59:(9,8,7..." effect, uncomment the alternative millis line below
     */
    private fun formatTime(remainingMillis: Long): String {
        val minutes = (remainingMillis / 1000 / 60).toString().padStart(2, '0')
        val seconds = (remainingMillis / 1000 % 60).toString().padStart(2, '0')
        // Full millisecond display (e.g., 10:59:999)
        val millis = (remainingMillis % 1000).toString().padStart(3, '0')
        
        // Alternative: Only show last digit of millis for the rapid jump effect (e.g., 10:59:9)
        // val millis = (remainingMillis % 10).toString()
        
        return "$minutes:$seconds:$millis"
    }
}

How to Use It (Android Example)

Integrate this into your Activity or Fragment easily:

import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private val countdownManager = CountdownManager()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val countdownText = findViewById<TextView>(R.id.countdown_text)

        // Start a 11-minute countdown (660 seconds = 10m59s)
        countdownManager.start(
            totalSeconds = 660,
            onTick = { formattedTime ->
                countdownText.text = formattedTime
            },
            onFinish = {
                Toast.makeText(this, "Countdown done!", Toast.LENGTH_SHORT).show()
            }
        )
    }

    // Always clean up the countdown to prevent memory leaks
    override fun onDestroy() {
        super.onDestroy()
        countdownManager.stop()
    }
}

Why This Works

  • Coroutines: We use CoroutineScope instead of Handler because it's safer (auto-cancels with lifecycle if you use viewLifecycleOwner in Fragments) and more readable.
  • 10ms Delay: By updating every 10ms instead of 1 second, the millisecond portion ticks rapidly—exactly the "9,8,7..." effect you're looking for.
  • Flexible Formatting: The formatTime function lets you switch between full millisecond display or just the last digit, depending on your UI needs.

Adaptation for Non-Android Kotlin

If you're using this in a plain Kotlin/JVM project, just adjust the CoroutineScope to use a background dispatcher (like Dispatchers.Default) and update your output method (e.g., print to console instead of updating a TextView):

// Example for Kotlin/JVM
fun main() {
    val manager = CountdownManager()
    manager.start(
        totalSeconds = 10,
        onTick = { println(it) },
        onFinish = { println("Countdown completed!") }
    )
    
    // Keep the program running (you'd handle this differently in production)
    Thread.sleep(11000)
    manager.stop()
}

内容的提问来源于stack exchange,提问作者as lan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:37:45