欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實(shí)現(xiàn)一個(gè)完美的倒計(jì)時(shí)功能

 更新時(shí)間:2021年11月11日 16:27:59   作者:鍵盤上的麒麟臂  
在Adroid應(yīng)用中,倒計(jì)時(shí)的功能使用的很多,例如點(diǎn)擊獲取短信驗(yàn)證碼之后的倒計(jì)時(shí)等等,這篇文章主要給大家介紹了關(guān)于利用Android如何實(shí)現(xiàn)一個(gè)完美的倒計(jì)時(shí)功能的相關(guān)資料,需要的朋友可以參考下

一. 已有倒計(jì)時(shí)方案存在的問(wèn)題

在開發(fā)倒計(jì)時(shí)功能時(shí)往往我們會(huì)為了方便直接使用CountDownTimer或者使用Handler做延時(shí)來(lái)實(shí)現(xiàn),當(dāng)然CountDownTimer內(nèi)部封裝也是使用的Handler。

如果只是做次數(shù)很少的倒計(jì)時(shí)或者不需要精確的倒計(jì)時(shí)邏輯那倒沒(méi)關(guān)系,比如說(shuō)我只要倒計(jì)時(shí)10秒,或者我大概5分鐘請(qǐng)求某個(gè)接口

但是如果是需要做精確的倒計(jì)時(shí)操作,比如說(shuō)手機(jī)發(fā)送驗(yàn)證碼60秒,那使用現(xiàn)有的倒計(jì)時(shí)方案就會(huì)存在問(wèn)題??赡苡行┡笥褯](méi)有注意到這一點(diǎn),下面我們就來(lái)簡(jiǎn)單分析一下現(xiàn)有倒計(jì)時(shí)的問(wèn)題。

1. CountDownTimer

這個(gè)可能是用得最多的,因?yàn)榉奖懵?。但其?shí)倒計(jì)時(shí)每一輪倒計(jì)時(shí)完之后都是存在誤差的,如果看過(guò)CountDownTimer的源碼你就會(huì)知道,他的內(nèi)部是有做校準(zhǔn)操作的。(源碼很簡(jiǎn)單這里就不分析了)

但是如果你認(rèn)真的測(cè)試過(guò)CountDownTimer,你就會(huì)發(fā)現(xiàn),即便它內(nèi)部有做校準(zhǔn)操作,他的沒(méi)一輪都是有偏差,只是他最后一次倒計(jì)時(shí)完之后的總共時(shí)間和開始倒計(jì)時(shí)的時(shí)間相比沒(méi)偏差。

什么意思呢,意思就是1秒,2.050秒,3.1秒......,這樣的每輪偏差,導(dǎo)致他會(huì)出現(xiàn)10.95秒,下一次12秒的情況,那它的回調(diào)中如果你直接做取整就會(huì)出現(xiàn)少一秒的情況,但實(shí)際是沒(méi)少的。

這只是其中的一個(gè)問(wèn)題,你可以不根據(jù)它的回調(diào)做展示,自己用一個(gè)整形累加做展示也能解決。但是他還有個(gè)問(wèn)題,有概率直接出現(xiàn)跳秒,就是比如3秒,下次直接5秒,這是實(shí)際的跳秒,是少了一次回調(diào)的那種。

跳秒導(dǎo)致你如果直接使用它可能會(huì)大問(wèn)題,你可能自測(cè)的時(shí)候沒(méi)發(fā)現(xiàn),到時(shí)一上線應(yīng)用在用戶那概率跳秒,那就蛋疼了。

2. Handler

不搞這么多花里胡哨的,直接使用Handler來(lái)實(shí)現(xiàn),會(huì)有什么問(wèn)題。

因?yàn)橹苯邮褂胔andler來(lái)實(shí)現(xiàn),沒(méi)有校準(zhǔn)操作,每次循環(huán)會(huì)出現(xiàn)幾毫秒的誤差,雖然比CountDownTimer的十幾毫秒的誤差要好,但是在基數(shù)大的倒計(jì)時(shí)情況下誤差會(huì)累計(jì),導(dǎo)致最終結(jié)果和現(xiàn)實(shí)時(shí)間差幾秒誤差,時(shí)間越久,誤差越大

3. Timer

直接使用Timer也一樣,只不過(guò)他每輪的誤差更小,幾輪才有1毫秒的誤差,但是沒(méi)有校準(zhǔn)還是會(huì)出現(xiàn)誤差累計(jì),時(shí)間越久誤差越大。

二. 自己封裝倒計(jì)時(shí)

既然無(wú)法直接使用原生的,那我們就自己做一個(gè)。

我們基于Handler進(jìn)行封裝,從上面可以看出主要為了解決兩個(gè)問(wèn)題,時(shí)間校準(zhǔn)和跳秒。自己寫一個(gè)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();

    }

}

思路就是在倒計(jì)時(shí)開始前獲取一次SystemClock.elapsedRealtime(),沒(méi)輪倒計(jì)時(shí)再獲取一次SystemClock.elapsedRealtime()相減得到誤差,根據(jù)delay校準(zhǔn)。然后使用while循壞來(lái)處理跳秒的操作,與原生的CountDownTimer不同,這里如果跳了多少秒,就會(huì)返回多少次回調(diào)。

總結(jié)

到此這篇關(guān)于利用Android實(shí)現(xiàn)一個(gè)完美的倒計(jì)時(shí)功能的文章就介紹到這了,更多相關(guān)Android倒計(jì)時(shí)功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論