Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
361 views
in Technique[技术] by (71.8m points)

java - Android: CountDownTimer skips last onTick()!

Code:

public class SMH extends Activity {  

    public void onCreate(Bundle b) {  
        super.onCreate(b);  
        setContentView(R.layout.main);  

        TextView tv = (TextView) findViewById(R.id.tv);  

        new CountDownTimer(10000, 2000) {  
            public void onTick(long m) {  
               long sec = m/1000+1;  
               tv.append(sec+" seconds remain
");  
            }  
            public void onFinish() {  
               tv.append("Done!");  
            }  
        }.start();  
   }

Output:
10 seconds remain
8 seconds remain
6 seconds remain
4 seconds remain
Done!

Problem:

How do I get it to show "2 seconds remain"? The time elapsed is indeed 10 seconds, but the last onTick() never happens. If I change the second parameter from 2000 to 1000, then this is the output:

10 seconds remain
9 seconds remain
8 seconds remain
7 seconds remain
6 seconds remain
5 seconds remain
4 seconds remain
3 seconds remain
2 seconds remain
Done!

So you see, it seems to be skipping that last onTick() call. And btw, the XML file is basically the default main.xml with the TextView assigned the id tv and the text set to "".

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I checked the source code of CountDownTimer. The "missing tick" comes from a special feature of CountDownTimer that I have not yet seen being documented elsewhere:

At the start of every tick, before onTick() is called, the remaining time until the end of the countdown is calculated. If this time is smaller than the countdown time interval, onTick is not called anymore. Instead only the next tick (where the onFinish() method will be called) is scheduled.

Given the fact that hardware clocks are not always super precise, that there may be other processes in the background that delay the thread running CountDownTimer plus that Android itself will probably create a small delay when calling the message handler of CountDownTimer it is more than likely that the call for the last tick before the end of the count down will be at least one millisecond late and therefore onTick() will not be called.

For my application I solved this problem simply by making the tick intervals "slightly" smaller (500 ms)

    myCountDownTimer = new CountDownTimer(countDownTime, intervalTime - 500) {
                                   ...
    }

and I could leave my code just as it is. For applications where the length of the interval time is critical, the other solutions posted here are probably the best.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...