咱们中国人做事情讲究吉利,我也不例外,所以就选今天这个良辰吉日来写出自己的第一篇博客文章吧!
一、引言
我们经常在电视中看到发生卫星的场景,大家都知道会有人在喊倒计时“5,4,3,2,1,发射!”,这个时候卫星就点火发射了。其实这些都是已经在程序当中写好了的,即使没有人喊,也一样会在那个时间发射。那么这个倒计时功能在java中是哪一个类来实现的呢?这个类就是今天的主角CountDownTimer类。
二、CountDownTimer类介绍
CountDownTimer类是一个抽象类,需要写一个子类来继承,如:
class TimeCount extends CountDownTimer {
public TimeCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onTick(long millisUntilFinished) {
mSend.setBackgroundColor(Color.parseColor("#B6B6D8"));
mSend.setClickable(false);
mSend.setText(millisUntilFinished / 1000 + " 秒后可重新发送");
}
@Override
public void onFinish() {
mSend.setText("重新获取验证码");
mSend.setClickable(true);
mSend.setBackgroundColor(Color.parseColor("#4EB84A"));
}
}
其中在构造方法中,参数millisInFuture代表设置倒计时的总时间(毫秒),参数countDownInterval代表设置每次减去的时间(毫秒)。onTick()方法是进行倒计时的时候开始运行的,onFinish()方法是倒计时结束之后运行的。
另外,CountDownTimer类还有start()和cancle()两个方法,调用start()方法会开始倒计时,调用cancle()方法取消当前任务。
三、实现倒计时按钮
private TimeCount time;
private Button mSend;
@Override
protected void onCreateView(Bundle savedInstanceState) {
super.onCreateView(savedInstanceState);
setContentView(R.layout.fragment_phone);
mSend = (Button) findViewById(R.id.btn_send);
time = new TimeCount(60000, 1000);
mSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
phone = mEtPhone.getText().toString();
if (TextUtils.isEmpty(phone)) {
CustomToast.showShortError(getApplicationContext(), "请输入账号");
return;
}
if (!CheckUtil.isPhoneLegal(phone)) {
CustomToast.showShortError(getApplicationContext(), "手机格式不合法");
return;
}
//发送请求
LoginHttpClient.getClient().sms(getApplicationContext(), phone, Constants.SMS_TYPE_MESSAGE, mScene, new ResponseListener<ResponseInfo>() {
@Override
public void onSuccess(ResponseInfo info) {
switch (info.errno) {
case Errno.OK:
Bundle bundle = new Bundle();
bundle.putString(Constants.BUNDLE_KEY_PHONE, phone);
bundle.putInt(Constants.BUNDLE_KEY_SCENE, mScene);
CustomToast.showShortComplete(getApplicationContext(), "短信验证码已发送");
//开启倒计时
time.start();
break;
case Errno.ACCOUNT_NOT_EXISTS:
CustomToast.showShortError(getApplicationContext(), "该用户未注册");
break;
default:
CustomToast.showShortError(getApplicationContext(), info.msg);
break;
}
}
@Override
public void onFail(Throwable throwable) {
CustomToast.showShortError(getApplicationContext(), "请稍后重试");
}
});
}
});
@Override
public void onDestroy() {
time.cancel();
super.onDestroy();
}
当发送请求时调用time.start()方法,开始倒计时60秒,并运行onTick()方法,改变button的样式,60秒倒计时结束的时候调用onFinish()方法。注意:不调用time.start()方法的话是不会开启倒计时的。在销毁activity的时候,调用cancle()方法,以防止内存泄漏和出现如空指针等异常。
四、注意事项
1、空指针:如果在activity或者fragment关闭销毁的时候没有调用cancle()方法,它的onTick()方法还是会继续执行,这个时候UI控件都为空,不注意判断的话很容易空指针。在重写onFinish()方法的时候加上一句“cancle()”就可以一劳永逸地解决这个问题了。
2、时间不是太准的问题:
我们看CountDownTimer的源码可以看到,在执行onTick的方法时,google源码里面减去了程序执行到这里的时候所消耗的时间,这里可以看出google代码的严谨。
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
}
所以一开始倒计时的时间是59,这里可以在构造方法里面稍微加一点时间就可以解决如:
new CountDownTimer(60 * 1000+300, 1000)
五、结束语
总的来说CountDownTimer类是十分简单、十分接地气的,用起来也很顺手。今天通过写这篇文章我把CountDownTimer类又看了一遍,重新总结了一下,可谓收获颇丰。那么第一篇文章就到这里吧,再见!ヾ( ̄▽ ̄)Bye~Bye~
参考:
1、https://blog.csdn.net/weixin_42564441/article/details/80967482