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.