倒计时器CountDownTimer使用

CountDownTimer使用—倒计时器实现

安卓提供了一个倒计时的类CountDownTimer,这个类会在固定的时间间隔回调方法,在执行计时结束后回调方法,方便操作;
示例代码

//创建一个时长30秒的倒计时器,倒计时间隔1秒,参数1为计时总时长,参数2为计时间隔
CountDownTimer countDownTimer = new CountDownTimer(30000, 1000) {
    //方法会在1秒后回调,参数millisUntilFinished表示剩余时间的毫秒值
    public void onTick(long millisUntilFinished) {
        mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
    }

    //计时器结束时执行的方法
    public void onFinish() {
        mTextField.setText("done!");
    }

};

//调用start方法开始计时
countDownTimer.start();

//调用cancel方法取消计时器结束计时
countDownTimer.cancel();

上面是计时器类简单使用,该计时器类没有暂停的方法,只能取消计时。

如果按照上面的方法使用,可能会出现问题,出现跳秒的问题,且在最后一秒时,显示时间较长,还有不会显示0秒的问题

这个问题是什么原因呢,我打印了onTick方法返回的剩余秒数值

从log日志可以看出,实际计时器onTick方法调用了4次,我设置的时间间隔是1s,但onTick返回的值第一次是5000ms,第二次应该是4000ms,但实际情况是返回的是3998ms,这样我用剩余秒数做处理获取秒值时,就会成为3s,也就是跳了1s,而在最后1s时,虽然显示的剩余1s,而实际是剩余时间接近2s的,因为之前计秒的误差,导致最后一次本应是2000ms的,实际成了小于2000ms的值,计算的话是1s,也就导致了最后一秒感觉时间不止1s,直观感觉卡了(实际并没有卡),计时器代码执行的时间会导致计秒出现误差,因此要解决误差的问题就需要对时间ms值进行补偿,那补多少呢?10ms?其实这个误差的值不同的设备不同,每次开启计时器误差也不同,并且设置的倒计时时间越长,这个误差到最后累计的也就越多,经过考虑决定设置添加500ms来进行误差补偿,增加500ms值不会影响计秒计算的结果。

增加500ms后日志打印结果

这样解决了跳秒的问题,但是有会出现一个问题,显示上现在是没问题了,但是看具体的时间,日志从31秒750开始打印的,结束为35秒756,剩余的还有1495ms,但是不会去执行onTick方法了,而是执行完剩下的1495ms后去执行onFinish方法了,实际计时时间为5.5s左右,这样是不对的,应该在计秒到0秒时,才结束计秒,计秒时长应该保证是5秒,为了解决问题,在总时长里面再增加1000ms,在处理显示的秒数时,应减去1s,判断剩余的秒数,秒数为0时就结束计时,调用cancel方法,调用onFinish方法去执行计时结束的逻辑,代码如下:

CountDownTimer countDownTimer = new CountDownTimer(5000+1500, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            long remainderTime = millisUntilFinished / 1000 - 1;
            //判断为1秒时,结束计时
            mTvCountTime.setText("millisUntilFinished" + remainderTime);
            LogUtils.e(remainderTime + "");
            if (remainderTime == 0) {
                onFinish();
                cancel();
            }
        }

        @Override
        public void onFinish() {
            mTvCountTime.setText("计时结束");
        }
    };

执行日志

执行效果

结果显示,日志打印了6条,开始时间为22秒937,结束时间为27秒943,这样就正常了,计秒数为5s,在剩余0s时,设置文本显示计时结束,这样的话倒计时就实现了,如果需要设置长时间计时,那就将上面代码中的5000改为你想设置的秒数值即可,

设置10秒倒计时日志

到此倒计时类实现倒计时完成。可以将这个类实现封装成工具类,方便以后调用,比如发送验证码时的倒计时,最后经过整理贴出实现倒计时的工具类,仅供参考抛砖引玉:

import android.annotation.SuppressLint;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.TextView;

/**
 * @author wodx521
 * @date on 2018/8/15
 */
public class CountDownTimerUtils {
    @SuppressLint("StaticFieldLeak")
    private static CountDownTimer timer;

    /**
    * 由于该倒计时类会存在不会显示0秒,且最后1秒实际是接近2秒的时间,因此处理时将剩余秒数多减了一秒
    * 在创建timer时,倒计时的秒数应该多加1秒,自动计时类计时时会产生毫秒值得误差,如果去整数的值
    * 在计算时可能会出现跳秒的情况(实际倒计时的秒数差的不大,就几十毫秒),为了给计秒做补偿,多加500毫秒
    * 保证误差同时也能保证计秒准确
    *
    * @param second      需要设置的倒计时秒数
    * @param view        倒计时运行时需要设置文本变化的控件TextView或者Button
    * @param defaultText 计时结束后view上显示的内容
    */
    public static void getTimer(int second, final View view, final String defaultText) {
        timer = new CountDownTimer(second * 1000 + 1500, 1000) {
            @SuppressLint("DefaultLocale")
            @Override
            public void onTick(long millisUntilFinished) {
                long remainderTime = millisUntilFinished / 1000 - 1;
                //判断view是否是TextView,如果是就设置显示倒计时的文本(Button是TextView子类)
                //如果是TextView的话,设置显示倒计时同时设置view不可点击
                if (view instanceof TextView) {
                ((TextView) view).setText(String.format("%ds", remainderTime));
                }
                if (remainderTime == 0) {
                    //判断为1秒时,结束计时,并恢复view可以点击
                    onFinish();
                    cancel();
                }
            }

            @Override
            public void onFinish() {
                view.setClickable(true);
                if (view instanceof TextView) {
                    ((TextView) view).setText(defaultText);
                }
            }
        };
        //开启计时器
        timer.start();
        //设置不能被点击
        view.setClickable(false);
    }

    /**
    * 取消计时器计时
    */
    public static void cancelTimer() {
        if (timer != null) {
            timer.cancel();
            timer.onFinish();
        }
    }
}

你可能感兴趣的:(安卓)