Search code examples
javaandroidmultithreadingtimercountdown

Android CountDownTimer Class Lagging Main Thread


I am trying to use android.os.CountDownTimer to literally show a countdown timer via a textview for fitness purposes. The issue I am having is the timer seems to be having trouble running on the main thread i.e. the countdown will jump 2-4 secs and is clearly being "lagged" - the timer is intended to be in an endless loop until a stop button is pressed.

I am new to Java and Android and cannot figure out how to get the countdown timer running and updating the UI without any conflicts or lagging.

I have attempted to put the CountDown in a Handler/Runnable and an Asynctask with no luck.

MainActivity

CountDownTimer timer;
void countdownTimer() {
    long min = countdownMins * 60000;
    long sec = countdownSecs * 1000;
    long milliseconds = min+sec;
    timer = null;
    timer = new CountDownTimer(milliseconds, 1000) {

        public void onTick(long millisUntilFinished) {

            long mins = millisUntilFinished / 60000;
            long secs = millisUntilFinished % 60000 / 1000;
            String display = String.format("%02d:%02d", mins, secs);
            tvTextView.setText(display);
        }
        public void onFinish() {
            countdownTimer();
        }
    }.start();
}

Many thanks to anyone who can show me how to get this running off the main thread so my UI elements will be smooth.


Solution

  • I decided to take a different approach which has served my purposes very well. No lag or thread issues and can easily be restarted over and over. Hope this helps someone out.

    int startCountdown = 5;
    int currentCountdown;
    Handler countdownHandler = new Handler();
    Timer countdownTimer = new Timer();
    public void startCountdownTimer() {
        currentCountdown = startCountdown;
        for (int i = 0; i <= startCountdown; i++) {
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                    countdownHandler.post(doA);
                }
            };
            countdownTimer.schedule(task, i * 1000);
        }
    }
    final Runnable doA = new Runnable() {
        @Override
        public void run() {
            if (currentCountdown != 0) {
                tvTextView.setText("" + currentCountdown);
            currentCountdown--;
            } else {
                currentCountdown = startCountdown;
                startCountdownTimer();
            }
        }
    };