Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android CountDownTimer shows 1 for two seconds [duplicate]

Tags:

android

Possible Duplicate:
How come millisUntilFinished cannot detect exact CountDownTimer intervals?

Why does using the CountDownTimer show "1" twice? I just want it to countdown smoothly and not look like it is getting hung up on the last second. Anybody have any ideas on how to solve this problem??

Here is the code from the Android Developers page:

  new CountdownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();

I created a new project and copied and pasted this code in just to make sure that I wasn't accidentally messing something up in my program. I've been testing this on a Tab 10.1. It does this when I run it: "5", "4", "3", "2", "1", "1", "done!".

like image 557
Mark Avatar asked Jul 24 '11 23:07

Mark


1 Answers

The CountDownTimer is not precise, it will return as close to 1 second (in this case) as it can but often that won't be enough to give you what you want.

If you Log the ms var you will see that the result is something like 29384 for the first hit, and so on, it will never be 30000, 29000 etc. There is no way to get the precision you need to make the counter work as you intended as currently implemented.

You can fix this for most cases. First lower you interval so that you get more updates than what you want to output, so instead of 1 second do 100ms and that should get you the illusions of a 1 second countdown timer since you will get at least a few updates per second (worst case)

To optimize that bit round the result on each entry and do a simple check to see if you should do the update (secondsLeft has changed) and if it has update the UI and the secondsLeft accumulator. Also I suggest that onFinish produce the final result (0) just in case the system glitches because something is happening that eats cpu cycles.

Anyway here is the modified code that works for this 99.99 times out of a 100 if your system is not loaded heavily. NOTE: You can probably get away with 250ms, up to you really.

 int secondsLeft = 0; 

 new CountDownTimer(30000, 100) {
     public void onTick(long ms) {
         if (Math.round((float)ms / 1000.0f) != secondsLeft)
         {  
             secondsLeft = Math.round((float)ms / 1000.0f);
             TV.setText("seconds remaining: " +secondsLeft );
         }
         Log.i("test","ms="+ms+" till finished="+secondsLeft );
     }

     public void onFinish() {
         TV.setText("0");
     }
}.start();
like image 180
Idistic Avatar answered Oct 14 '22 06:10

Idistic