android CountDownTimer - 刻度之间的额外毫秒延迟

dor*_*uck 7 android

从我的观察来看,滴答之间的android CountDownTimer countDownInterval恰好不准确,countDownInterval通常比指定的时间长几毫秒.我的特定应用程序中的countDownInterval是1000毫秒,只需一秒钟倒计时一定时间.

由于这个延长的滴答声,我最终得到的滴答数减少了当倒计时器运行足够长时间,这会缩短所显示的倒计时时间(当有足够的额外ms总结时,在UI级别上发生2秒的步骤)

查看CountDownTimer的来源似乎可以扭曲它,以便纠正这种不必要的不​​准确性,但我想知道在java/android世界中是否已经有更好的CountDownTimer可用.

感谢所有指针的好友......

Sam*_*Sam 16

改写

正如你所说,你也注意到下一次进入onTick()是从上一次onTick()运行的时间计算出来的,这会在每次滴答时引入一个小错误.我更改了CountDownTimer源代码,onTick()从开始时间开始以指定的间隔调用每个源代码.

我在CountDownTimer框架上构建它,因此将源代码剪切并粘贴到项目中,并为类提供唯一的名称.(我称之为MoreAccurateTimer.)现在进行一些更改:

  1. 添加一个新的类变量:

    private long mNextTime;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 变化start():

    public synchronized final MoreAccurateTimer start() {
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
    
        mNextTime = SystemClock.uptimeMillis();
        mStopTimeInFuture = mNextTime + mMillisInFuture;
    
        mNextTime += mCountdownInterval;
        mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG), mNextTime);
        return this;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 更改处理程序handlerMessage():

    @Override
    public void handleMessage(Message msg) {
        synchronized (MoreAccurateTimer.this) {
            final long millisLeft = mStopTimeInFuture - SystemClock.uptimeMillis();
    
            if (millisLeft <= 0) {
                onFinish();
            } else {
                onTick(millisLeft);
    
                // Calculate next tick by adding the countdown interval from the original start time
                // If user's onTick() took too long, skip the intervals that were already missed
                long currentTime = SystemClock.uptimeMillis();
                do {
                    mNextTime += mCountdownInterval;
                } while (currentTime > mNextTime);
    
                // Make sure this interval doesn't exceed the stop time
                if(mNextTime < mStopTimeInFuture)
                    sendMessageAtTime(obtainMessage(MSG), mNextTime);
                else
                    sendMessageAtTime(obtainMessage(MSG), mStopTimeInFuture);
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)