温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android怎样实现倒计时功能

发布时间:2021-11-12 13:20:27 来源:亿速云 阅读:131 作者:小新 栏目:开发技术

这篇文章主要为大家展示了“Android怎样实现倒计时功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Android怎样实现倒计时功能”这篇文章吧。

一. 已有倒计时方案存在的问题

在开发倒计时功能时往往我们会为了方便直接使用CountDownTimer或者使用Handler做延时来实现,当然CountDownTimer内部封装也是使用的Handler。

如果只是做次数很少的倒计时或者不需要精确的倒计时逻辑那倒没关系,比如说我只要倒计时10秒,或者我大概5分钟请求某个接口

但是如果是需要做精确的倒计时操作,比如说手机发送验证码60秒,那使用现有的倒计时方案就会存在问题。可能有些朋友没有注意到这一点,下面我们就来简单分析一下现有倒计时的问题。

1. CountDownTimer

这个可能是用得最多的,因为方便嘛。但其实倒计时每一轮倒计时完之后都是存在误差的,如果看过CountDownTimer的源码你就会知道,他的内部是有做校准操作的。(源码很简单这里就不分析了)

但是如果你认真的测试过CountDownTimer,你就会发现,即便它内部有做校准操作,他的没一轮都是有偏差,只是他最后一次倒计时完之后的总共时间和开始倒计时的时间相比没偏差。

什么意思呢,意思就是1秒,2.050秒,3.1秒......,这样的每轮偏差,导致他会出现10.95秒,下一次12秒的情况,那它的回调中如果你直接做取整就会出现少一秒的情况,但实际是没少的。

这只是其中的一个问题,你可以不根据它的回调做展示,自己用一个整形累加做展示也能解决。但是他还有个问题,有概率直接出现跳秒,就是比如3秒,下次直接5秒,这是实际的跳秒,是少了一次回调的那种。

跳秒导致你如果直接使用它可能会大问题,你可能自测的时候没发现,到时一上线应用在用户那概率跳秒,那就蛋疼了。

2. Handler

不搞这么多花里胡哨的,直接使用Handler来实现,会有什么问题。

因为直接使用handler来实现,没有校准操作,每次循环会出现几毫秒的误差,虽然比CountDownTimer的十几毫秒的误差要好,但是在基数大的倒计时情况下误差会累计,导致最终结果和现实时间差几秒误差,时间越久,误差越大

3. Timer

直接使用Timer也一样,只不过他每轮的误差更小,几轮才有1毫秒的误差,但是没有校准还是会出现误差累计,时间越久误差越大。

二. 自己封装倒计时

既然无法直接使用原生的,那我们就自己做一个。

我们基于Handler进行封装,从上面可以看出主要为了解决两个问题,时间校准和跳秒。自己写一个CountDownTimer

public class CountDownTimer {

    private int mTimes;
    private int allTimes;
    private final long mCountDownInterval;
    private final Handler mHandler;
    private OnTimerCallBack mCallBack;
    private boolean isStart;
    private long startTime;

    public CountDownTimer(int times, long countDownInterval){
        this.mTimes = times;
        this.mCountDownInterval = countDownInterval;
        mHandler = new Handler();
    }

    public synchronized void start(OnTimerCallBack callBack){
        this.mCallBack = callBack;
        if (isStart || mCountDownInterval <= 0){
            return;
        }

        isStart = true;
        if (callBack != null){
            callBack.onStart();
        }
        startTime = SystemClock.elapsedRealtime();

        if (mTimes <= 0){
            finishCountDown();
            return;
        }
        allTimes = mTimes;

        mHandler.postDelayed(runnable, mCountDownInterval);
    }

    private final Runnable runnable = new Runnable() {
        @Override
        public void run() {
            mTimes--;
            if (mTimes > 0){
                if (mCallBack != null){
                    mCallBack.onTick(mTimes);
                }

                long nowTime = SystemClock.elapsedRealtime();
                long delay = (nowTime - startTime) - (allTimes - mTimes) * mCountDownInterval;
                // 处理跳秒
                while (delay > mCountDownInterval){
                    mTimes --;
                    if (mCallBack != null){
                        mCallBack.onTick(mTimes);
                    }

                    delay -= mCountDownInterval;
                    if (mTimes <= 0){
                        finishCountDown();
                        return;
                    }
                }

                mHandler.postDelayed(this, 1000 - delay);
            }else {
                finishCountDown();
            }
        }
    };

    private void finishCountDown(){
        if (mCallBack != null){
            mCallBack.onFinish();
        }
        isStart = false;
    }

    public void cancel(){
        mHandler.removeCallbacksAndMessages(null);
        isStart = false;
    }

    public interface OnTimerCallBack{

        void onStart();

        void onTick(int times);

        void onFinish();

    }

}

思路就是在倒计时开始前获取一次SystemClock.elapsedRealtime(),没轮倒计时再获取一次SystemClock.elapsedRealtime()相减得到误差,根据delay校准。然后使用while循坏来处理跳秒的操作,与原生的CountDownTimer不同,这里如果跳了多少秒,就会返回多少次回调。

以上是“Android怎样实现倒计时功能”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI