借助CountDownTimer类实现获取验证码倒计时按钮

    咱们中国人做事情讲究吉利,我也不例外,所以就选今天这个良辰吉日来写出自己的第一篇博客文章吧!

一、引言

    我们经常在电视中看到发生卫星的场景,大家都知道会有人在喊倒计时“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

原创文章 19 获赞 34 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_38141453/article/details/83213231
今日推荐