It is often encountered in the APP to implement the countdown function. Since the Android framework has built-in countdown functionality, you don’t have to write your own Handler to do it.

Android. OS has an abstract class called CountDownTimer. You can inherit this class and rewrite fun onTick(zipuntilfinished: Long) and fun onFinish().


If you look closely at the CountDownTimer source code, it is implemented using a Handler. The source code is as follows:

 // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }
                // Calculate the remaining time
                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
                // If the remaining implementation is less than or equal to zero, the current handler is terminated
                if (millisLeft <= 0) {
                    onFinish();
                } else {
                    // The time when the usage method is invoked
                    long lastTickStart = SystemClock.elapsedRealtime();
                    // Call onTick with the remaining time as an argument
                    onTick(millisLeft);

                    // To prevent delays in executing the user's code, record the time it takes to execute the user's methods
                    // take into account user's onTick taking time to execute
                    long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;
                    long delay;

                    // If the remaining time is less than the countdown interval
                    if (millisLeft < mCountdownInterval) {
                        // just delay until done
                        // Calculate delay
                        delay = millisLeft - lastTickDuration;

                        // special case: user's onTick took more than interval to
                        // complete, trigger onFinish without delay
                        if (delay < 0) delay = 0;
                    } else {
                        delay = mCountdownInterval - lastTickDuration;

                        // special case: user's onTick took more than interval to
                        // complete, skip to next interval
                        while (delay < 0) delay += mCountdownInterval; } sendMessageDelayed(obtainMessage(MSG), delay); }}}};Copy the code

CountDownTimer(zipinfuture, countDownInterval): a constructor of CountDownTimer. The first argument takes the time you want to time, and the second argument takes the interval, such as 1S. Note: All parameters here are in milliseconds (1 second =1000 milliseconds)

Fun onTick(zipuntilfinished: Long): is the method called during timing, like updating the UI and so on.

Fun onFinish() : is the method called when timing ends.


If you want to convert milliseconds and minutes into seconds and minutes, you can do it quickly using the TimeUnit class. Want to change MILLISECONDS to seconds, for example, can TimeUnitTimeUnit. MILLISECONDS. ToSeconds (MILLISECONDS) to complete.


So the overall countdown method is as follows:

class CountDown(
        millisInFuture: Long,
        countDownInterval: Long
    ) : CountDownTimer(millisInFuture, countDownInterval) {
        @SuppressLint("SetTextI18n")
        override fun onTick(millisUntilFinished: Long) {
            val minutes = TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)
            val seconds = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) % 60

            // Convert to 2 digits
            val minutesStr = String.format("%02d", minutes)
            val secondsStr = String.format("%02d", seconds)
            // Convert to time format
            _leftTime.value = "$minutesStr:$secondsStr"
        }

        override fun onFinish(a) {
            //TODO: Implement the function of the end of the countdown here}}Copy the code

Finally, instantiate the CountDown class and call the start() method to start the CountDown.

val countDown = CountDown(10000.1000)
count.start()
Copy the code

Cancel the countdown by calling count.cancel().