在Android 中倒計時功能是比較普遍使用的一個功能,比如手機驗證碼,計時執行命令等。實現方式有Handler、Thread 等,但是實現起來都比較複雜,過於麻煩,需要自己去寫很多代碼。今天講講在Android中如何用CountDownTimer 非常簡單的實現倒計時功能。
先看看CountDownTimer 類源碼,我們先來熟悉它的構造,再動手。CountDownTimer 實現倒計時功能的機制也是用Handler 消息控制,只是它幫我們已經封裝好了,我們可以直接實現類提供的方法就可以寫自己的業務邏輯了。下面先從該類的描述看起。
大致描述是 設置一個倒計時時間,直到完成一個時間段的計時,並且會時時更新時間的變化,舉了一個30秒倒計時的例子如下
<code> new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();/<code>
從這個例子中可以看出,他有一個構造方法,傳入了兩個參數。
<code>/**
* @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;
}/<code>
第一個參數傳入設置倒計時的總時間,第二個參數傳入每隔多少毫秒執行一次,注意這裡傳入的兩個時間參數的單位都是毫秒。如我要定義一個一分的倒計時,每隔一秒執行一次,傳參時就應該是 new CountDownTimer(60000, 1000)。
下面看看提供的這幾個方法。
<code>/**
* Cancel the countdown.
*/
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
/**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
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();/<code>
cancel() 從字面上也理解到,它就是取消倒計時的意思.通過Handler removeMessages 取消正在執行的倒計時任務。start() 開始執行倒計時。通過Handler sendMessage 發送消息並開始執行倒計時任務。onTick() 倒計時更新。這裡可以得到距離完成倒計時還剩多少時間。onFinish() 倒計時完成後的回調。
我們再來看看Handler 實現部分
<code> // 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);
}
}
}
};/<code>
這裡主要是輪詢計算時間,調用 onTick() 方法更新當前倒計時時間,當mStopTimeInFuture 減去 SystemClock.elapsedRealtime()(boot 以來經過的毫秒數)小於等於 0 時 ,則調用 onFinish()。
下面我們簡單寫一個實現倒計時的demo 為了代碼維護和重用,我這裡寫一個公共的倒計時 CommonCountDownTimer 類,代碼如下:
<code>import android.os.CountDownTimer;
/**
* 公共倒計時類
*/
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() {
if (null != countDownTimerListener){
countDownTimerListener.onFinish();
}
}
public interface OnCountDownTimerListener {
/**
* 更新倒計時時間
*
* @param millisUntilFinished
*/
void onTick(long millisUntilFinished);
/**
* 完成倒計時
*/
void onFinish();
}
}
/<code>
這裡的CommonCountDownTimer 類繼承了 android.os.CountDownTimer 類,我定義了一個 OnCountDownTimerListener 接口主要來監聽 onTick(long millisUntilFinished) 和 onFinish() ,這樣可以把業務邏輯分開來處理。
開始使用
<code> private void initCountDownTimer() {
mCountDownTimer = new CommonCountDownTimer(60000, 1000);
mCountDownTimer.setCountDownTimerListener(new CommonCountDownTimer.OnCountDownTimerListener() {
@Override
public void onTick(long millisUntilFinished) {
tv_time.setText("倒計時:" + millisUntilFinished / 1000);
}
@Override
public void onFinish() {
tv_time.setText("倒計時: 00");
}
});
}/<code>
就是這麼簡單,主要需要理解 CountDownTimer 這個類,理解了之後就可以根據自己的業務場景靈活使用了。由於本人很菜,有些地方認識理解不對的地方歡迎,謝謝大家指正。
題圖: pixabay
閱讀更多 ProgrammerRan 的文章