In Android, the countdown function is a widely used function, such as mobile phone verification code, timing execution command, etc. The implementation methods include Handler, Thread, etc., but the implementation is complicated and too troublesome, and you need to write a lot of code by yourself. Today I’ll show you how to use CountDownTimer in Android to implement the countdown function very easily.

Take a look at the source code of the CountDownTimer class. Let’s get familiar with its construction before we start. CountDownTimer implements the countdown function using Handler message control, but it has been wrapped to help us, we can directly implement the method provided by the class can write their own business logic.

/** * Schedule a countdown until a time in the future, with * regular notifications on intervals along the way. * * Example of showing a 30 second countdown in a text field: * * <pre class="prettyprint"> * new CountDownTimer(30000, 1000) { * * public void onTick(long millisUntilFinished) { * mTextField.setText("seconds remaining: " + millisUntilFinished / 1000); * } * * public void onFinish() { * mTextField.setText("done!" ); * } * }.start(); * </pre> * * The calls to {@link #onTick(long)} are synchronized to this object so that
 * one call to {@link #onTick(long)} won't ever occur before the previous
 * callback is complete.  This is only relevant when the implementation of
 * {@link #onTick(long)} takes an amount of time to execute that is significant
 * compared to the countdown interval.
 */
Copy the code

The general description is to set a countdown time until the completion of a period of time, and will update the time change from time to time, take a 30-second countdown example as follows

new CountDownTimer(30000.1000) {

      public void onTick(long millisUntilFinished) {
          mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
      }

      public void onFinish(a) {
          mTextField.setText("done!");
      }
   }.start();
Copy the code

We can see from this example that he has a constructor that takes two arguments.

 / * * *@param millisInFuture The number of millis in the future from the call
     *   to {@link #start()} until the countdown is done and {@link #onFinish()}
     *   is called.
     * @param countDownInterval The interval along the way to receive
     *   {@link #onTick(long)} callbacks.
     */
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }
Copy the code

The first parameter is passed to set the total time of the countdown, and the second parameter is passed to set the number of milliseconds in which the countdown is executed. Note that both time parameters are passed in milliseconds. If I wanted to define a one-minute countdown every second, I would pass the new CountDownTimer(60000, 1000).

Let’s take a look at the methods provided.

 /** * Cancel the countdown. */
    public synchronized final void cancel(a) {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    /** * Start the countdown. */
    public synchronized final CountDownTimer start(a) {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }


    /**
     * Callback fired on regular interval.
     * @param millisUntilFinished The amount of time until finished.
     */
    public abstract void onTick(long millisUntilFinished);

    /** * Callback fired when the time is up. */
    public abstract void onFinish(a);

Copy the code

Cancel () = cancel the countdown. Cancel a countdown task using Handler removeMessages. Start () starts the countdown. Send the message via Handler sendMessage and start the countdown task. OnTick () countdown update. This is how much time we have left before we finish the countdown. OnFinish () the callback after the countdown is complete.

Let’s take a look at the Handler implementation

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

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;
                    long delay;

                    if (millisLeft < mCountdownInterval) {
                        // just delay until done
                        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

Here is primarily a polling computing time, call onTick () method updates the countdown time, when mStopTimeInFuture minus the SystemClock. ElapsedRealtime () (after the number of milliseconds since boot) less than or equal to zero, OnFinish () is called.

For code maintenance and reuse, I will write a public countdown downtimer class. The code is as follows:

import android.os.CountDownTimer;
/** * Public countdown class */
public class CommonCountDownTimer extends CountDownTimer {

    private OnCountDownTimerListener countDownTimerListener;

    public void setCountDownTimerListener(OnCountDownTimerListener listener) {
        this.countDownTimerListener = listener;
    }

    / * * *@param millisInFuture    The number of millis in the future from the call
     *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
     *                          is called.
     * @param countDownInterval The interval along the way to receive
     *                          {@link #onTick(long)} callbacks.
     */
    public CommonCountDownTimer(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onTick(long millisUntilFinished) {
        if (null != countDownTimerListener) {
            countDownTimerListener.onTick(millisUntilFinished);
        }
    }

    @Override
    public void onFinish(a) {
        if (null != countDownTimerListener){
            countDownTimerListener.onFinish();
        }
    }


    public interface OnCountDownTimerListener {
        /** * Update the countdown time **@param millisUntilFinished
         */
        void onTick(long millisUntilFinished);

        /** * complete the countdown */
        void onFinish(a); }}Copy the code

Here CommonCountDownTimer class inherits the android. OS. CountDownTimer class, I’ve defined an OnCountDownTimerListener interface to listen for onTick(long millisUntilFinished) and onFinish() to separate business logic.

Begin to use

private void initCountDownTimer(a) {
        mCountDownTimer = new CommonCountDownTimer(60000.1000);
        mCountDownTimer.setCountDownTimerListener(new CommonCountDownTimer.OnCountDownTimerListener() {
            @Override
            public void onTick(long millisUntilFinished) {
                tv_time.setText("Countdown :" + millisUntilFinished / 1000);
            }

            @Override
            public void onFinish(a) {
                tv_time.setText("Countdown: 00"); }}); }Copy the code

It’s as simple as that. The main thing you need to understand is the CountDownTimer class, so you can use it flexibly for your own business scenarios. As I am very vegetables, some places to understand the wrong place welcome, thank you for correcting. If you feel good, you can follow the public account ProgrammerRan for more content.