3

I was using a CountDownTimer for some countdown functionality I have in my Activity. I decided to move away from CountDownTimer and use ScheduledThreadPoolExecutor because CountDownTimers can't cancel themselves in onTick().

For some reason, my Runnable in the following code only executes once. I'm not sure why it isn't executing multiple times. The destroyCountdownTimer() function is not getting hit.

private ScheduledThreadPoolExecutor mCountdownTimer;
private Tick mTick;

class Tick implements Runnable {
    @Override
    public void run() {
        Log.e("tick", String.valueOf(mAccumulatedMilliseconds));
        mAccumulatedMilliseconds += 1000;
        populateTimeAccumulated();
        populateTimeRemaining();
        updatePercentages();

        if (mTotalMilliseconds <= mAccumulatedMilliseconds) {
            destroyCountdownTimer();
        }
    }
}

private void startCountdown() {
    if (mAccumulatedMilliseconds < mTotalMilliseconds) {
        mCounterIsRunning = true;

        if (mCountdownTimer == null) {
            mCountdownTimer = new ScheduledThreadPoolExecutor(1);
        }

        if (mTick == null) {
            mTick = new Tick();
        }

        mCountdownTimer.scheduleAtFixedRate(mTick, 1000, 1000, TimeUnit.MILLISECONDS);
    }
}

private void destroyCountdownTimer() {
    if (mCountdownTimer != null) {
        mCountdownTimer.shutdownNow();
        mCountdownTimer = null;
    }

    if (mTick != null) {
        mTick = null;
    }
}
Andrew
  • 20,756
  • 32
  • 99
  • 177
  • Add logging to your cancellation logic (or if you must, use the breakpoint debugger) and see if that is triggering. – Chris Stratton Apr 08 '15 at 18:17
  • I've set a breakpoint in the call to destroy the timer. It is not being hit. After commenting out the populate/update calls inside the `Runnable`, everything is working fine. I see no reason why any of them should be holding up the `Runnable`. They were all functioning perfectly fine when I was using a `CountDownTimer`. I will update the main post with the code inside of them in a moment. – Andrew Apr 08 '15 at 18:22

1 Answers1

5

The documentation says:

If any execution of the task encounters an exception, subsequent executions are suppressed.

Add try-catch block to your Tick runnable.

Ircover
  • 2,406
  • 2
  • 22
  • 42
  • There is an exception inside `populateTimeAccumulated()`. – Andrew Apr 08 '15 at 18:24
  • 04-08 13:24:03.609: E/Tick(2722): error: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. – Andrew Apr 08 '15 at 18:25
  • Do I need to pass a pointer to the `Activity` to the `Runnable` or something? – Andrew Apr 08 '15 at 18:25
  • Need to make all actions with view in UI thread. For that you can use [runOnUiThread](http://stackoverflow.com/questions/11254523/android-runonuithread-explanation) method of Activity - do everything inside its runnable. – Ircover Apr 08 '15 at 18:38