Android countdown is generally implemented as follows:

  • The handler + postDelayed () method
  • The Timer + TimerTask + Handler mode is used
  • ScheduledExecutorService + Handler mode
  • RxJava way
  • CountDownTimer way

Now, with coroutines and Flow, we can use the Flow tool to implement this requirement more elegantly.

1. Rely on imports

    api 'org. Jetbrains. Kotlinx: kotlinx coroutines -- core: 1.4.2'
    api 'org. Jetbrains. Kotlinx: kotlinx coroutines - android: 1.4.1'
    // lifecycleScope(optional)
    api "Androidx. Lifecycle: lifecycle - runtime - KTX: 2.2.0." "
Copy the code

2. Code implementation

fun countDownCoroutines(
    total: Int,
    scope: CoroutineScope,
    onTick: (Int) - >Unit,
    onStart: (() -> Unit)? = null,
    onFinish: (() -> Unit)? = null.): Job {
    return flow {
        for (i in total downTo 0) {
            emit(i)
            delay(1000) } }.flowOn(Dispatchers.Main) .onStart { onStart? .invoke() } .onCompletion { onFinish? .invoke() } .onEach { onTick.invoke(it) } .launchIn(scope) }Copy the code
2.1 use:
private var mCountdownJob: Job? = null

mBinding.btnStart.setOnClickListener {
    mCountdownJob = countDownCoroutines(60, lifecycleScope,
        onTick = { second ->
            mBinding.text.text = "${second}Resend after s"
        }, onStart = {
            // The countdown begins
        }, onFinish = {
            // When the countdown ends, reset the status
            mBinding.text.text = "Send verification code"
        })
}

mBinding.btnStop.setOnClickListener { 
    // Cancel the countdownmCountdownJob? .cancel() }Copy the code

Other full demos github.com/dahui888/ko…