In trying to limit battery usage I need to not have busy loops, so I am not certain how to solve this problem.
If I have a program that will allow someone to sing for 45 seconds, then they pause for 20 seconds to get a drink, then repeat, for some number of songs.
My timer is at Problem getting timer to work after cancelling one iteration and starting another, but in order for this to work, when someone clicks on a button it starts the first countdown, but the times were queued up, and the title were displayed, then when the time is done it will show Rest, then after 20 seconds it will show a new title.
So use sendMessageDelayed
is a problem, though it works for the first part.
Ideally I would like to have the Runnable
return when the countdown is reached, to some controller function that would then use an if statement.
void Controller(int curCount) {
if(curCount % 2 == 0) {
// call thread that uses runnable with next song time limit and title
} else {
// call thread with 20 and "REST"
}
}
But, this would only work if
Thread t = new Thread(runnable);
... // Go to controller, which will count down
t.join();
blocked until done. I could do t.wait(time * 1000);
instead of t.join()
, but that may be a bit late or early as the timer won't be perfect at keeping time, so I don't think it is correct.
So what is the best way to do something like this, without needless polling or busy loops.
for(SongModel m : songList) {
countdownTime(m.getSongTime(), m.getTitle);
countdownTime(10, "REST");
}
Edit:
I think I was unclear about the problem with my current timer. Since the messages are queued up it will change to Rest while still counting down the time left for the first song, since the Runnable
finishes much more quickly than the Handler
is processing. So, there is a flaw in this approach that leads me to think for this design using a sendMessageDelayed
won't work as I had hoped, though, if I just need to count down once/button click it will be fine, but my needs are to have this all happen with one button click, it starts the process, and then should simulate the for
loop at the end of my question.
I would do this with a
Timer
and a pair ofTimerTasks
.The important thing is that I don't schedule the next timer until after the last one expires. You could adjust the times dynamically if you want the songTask to last for the length of the current song (as your code suggests) or 45 seconds (as your prose suggests). Either way, the basics are the same.
Here we are again :)
I wrote this and tested it in Eclipse with an Eclair emulator, and running fine. One click counts from 54 to 0, then from 20 to 0, then 45 to 0, etc., until another click cancels it. Let me know if it's up to your needs. Of course the UI is just the bare minimum:
TimerTest.java
main.xml
strings.xml