在app中经常会遇到要实现倒计时功能。因为安卓框架自带倒计时功能,所以可以不用自己手写Handler去实现。
android.os中有叫CountDownTimer的抽象类。可以继承该类,重写fun onTick(millisUntilFinished: Long)和fun onFinish()即可。
如果仔细探究CountDownTimer的源码,它的实现是方式用的是Handler。 源码如下:
// 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();
// 如果剩余实现小于等于0, 则结束当前的handler
if (millisLeft <= 0) {
onFinish();
} else {
// 调用用法方法开始的时间
long lastTickStart = SystemClock.elapsedRealtime();
// 把剩余时间当作参数,调用onTick方法
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);
}
}
}
};
CountDownTimer(millisInFuture, countDownInterval):
CountDownTimer的构造方法。第一个参数时想要计时的时间,第二个参数时计时间隔,比如1S。注意:这里所有参数的单位都是毫秒(1秒=1000毫秒)
fun onTick(millisUntilFinished: Long):
是计时过程中调用的方法,比如更新UI等等。
fun onFinish():
是当计时结束时调用的方法。
如果想要把毫秒和转换成秒和分, 则可以使用TimeUnit类可以快速实现。
比如想把毫秒换成秒,则可以TimeUnitTimeUnit.MILLISECONDS.toSeconds(milliseconds)来完成。
所以整体倒计时的实现方法时如下:
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
// 转换成2位数字
val minutesStr = String.format("%02d", minutes)
val secondsStr = String.format("%02d", seconds)
// 转换成表示时间的格式
_leftTime.value = "$minutesStr:$secondsStr"
}
override fun onFinish() {
//TODO : 在这里实现倒计时结束时的功能
}
}
最后实例化CountDown类,并调用start()方法来开始倒计时。
val countDown = CountDown(10000,1000)
count.start()
取消倒计时调用count.cancel()来取消。