Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CountDownTimer skipping one second when displaying on TextView

I want to display a simple CountDownTimer in a TextView, but it seems to go from 30 down to 28 right away, as if there was a lag in between. I'm not sure how to go about on fixing this small bug. Here is my code:

This is in the click listener of the Button:

new CountDownTimer(30000, 1000) {

    @Override
    public void onTick(long millisUntilFinished) {
        coolDownTimer.setText("Cool Down for: " + String.valueOf(millisUntilFinished / 1000));
    }

    @Override
    public void onFinish() {
        animatedPic.setClickable(true);
        // reregister the proximity sensor
        sm.registerListener(sensorListener, proxSensor, SensorManager.SENSOR_DELAY_NORMAL);
        coolDownTimer.setText("GO!");
    }
}.start();
like image 955
Mo2 Avatar asked Jun 03 '14 23:06

Mo2


2 Answers

There are 2 issues:

  • The first issue is that the countdown timer doesn't execute until time has elapsed for the first tick, in this case, after 1000ms.

  • The second is that the elapsed time is only approximate. millisUntilFinished is not guaranteed to come in increments of the interval (you can see that if you don't divide by 1000, the first tick is slightly under 29000).

Another thing to keep in mind is that you're not guaranteed to receive a tick call. That is to say, if the device did not have enough time to complete a tick, it may skip it (generally only noticeable for faster intervals).

To solve issue 1, you can simply run the onTick code (or refactor it into its own method) and run it as you start the countdown timer.

For issue 2, you can simply round the number.

For example:

new CountDownTimer(30000, 1000)
   {
        @Override
        public void onTick(long millisUntilFinished)
        {
            performTick(millisUntilFinished);
        }
        @Override
        public void onFinish()
        {
            animatedPic.setClickable(true);
            // reregister the proximity sensor
            sm.registerListener(sensorListener,proxSensor,SensorManager.SENSOR_DELAY_NORMAL);
            coolDownTimer.setText("GO!");
        }
    }.start();

    performTick(30000);


void performTick(long millisUntilFinished) {
    coolDownTimer.setText("Cool Down for: " + String.valueOf(Math.round(millisUntilFinished * 0.001f)));
}


If you want to make sure the appropriate value is updated with minimal latency, you may want to consider reducing the interval.

like image 124
Allen G Avatar answered Sep 21 '22 17:09

Allen G


It is skipping because CountDownTimer is not a precise timer. Try to print just the millisUntilFinished without dividing it you'll see some excess number that it wont be exactly 29000 when it hits its first tick.

you can refer on this thread for the solution.

like image 27
Rod_Algonquin Avatar answered Sep 17 '22 17:09

Rod_Algonquin