简体   繁体   中英

How can I call a method at regular intervals inside of a CountDownTimer?

What my code does: My activity has a CountDownTimer that starts when a user presses a button. When it completes, a sound is played. Here's the code:

public class PrepTimer extends CountDownTimer {
    public PrepTimer(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onTick(long millisUntilFinished) {
        updateSessionRemaining(millisUntilFinished);
        setPrepDigits(millisUntilFinished);
    }

    @Override
    public void onFinish() {
        session.setPrepRemaining(0);
        playSound();
    }
}

What I'd like it to do: I'd like the sound to play at regular intervals over the course of the timer (in addition to at the end). For example, in a ten minute timer, the sound might play every 60 seconds.

Things I've tried:

  • Using an if statement inside the onTick method to check when millisUntilFinished is equal to a certain value (a multiple of 60 seconds, for example) and then running the method. This seems like the most straightforward solution, but I've found that the method is not triggered consistently (perhaps millisUntilFinished is skipping over the value I'm checking it against?).
  • Creating separate, nested CountDownTimers and repeating with a for loop. The problem with this is that the code quickly becomes overly complicated and my intuition tells me that I shouldn't be running timers within timers.

Question: How can I run a method at regular intervals over the course of a CountDownTimer?

Instead of using a countdown timer you can simply use a post delayed Handler and thread.At the end of the method post the handler with specified time interval as below code

Runnable myThread = new Runnable() {
    @Override
    public void run() {
        //call the method here
        myHandler.postDelayed(myThread, 1000);//calls thread after 60 seconds
    }
};
myHandler.post(myThread);//calls the thread for the first time

After thinking on this for a while I came up with a solution that satisfies my chief requirement of simplicity. Here's how to employ it:

Declare two class-level variables

private long startTime = 60000; // Set this equal to the length of the CountDownTimer
private long interval = 10000; // This will make the method run every 10 seconds  

Declare a method to run on an interval inside the CountDownTimer

private void runOnInterval(long millisUntilFinished) {
    if (millisUntilFinished < startTime) {
        playSound();
        startTime -= interval;
    }
}

And then call the method in the onTick method of the CountDownTimer

// ...
@Override
    public void onTick(long millisUntilFinished) {
        runOnInterval(millisUntilFinished);
    }
// ...

And here's how it works: The onTick method of the CountDownTimer passes millisUntilFinished each time it ticks. Then runOnInterval() checks to see if that value is less than startTime . If it is, it runs the code inside the if statement (in my case, playSound() ) and then decrements startTime by the value of interval . Once millisUntilFinished is lower than startTime again, the process starts all over again.

The above code is simpler than employing another CountDownTimer or a Handler and a Runnable . It also automatically works with any sort of functionality one might have added to the activity to handle CountDownTimer pauses and resets.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM