How to pause, and resume a TimerTask/ Timer
Asked Answered
H

4

22

I have an animation in my Android app that flashes a TextView different colors. I've used a TimerTask, Timer, and Runnable method to implement this. What I need to do is stop the thread when a user leaves the app during this animation in onPause(), and resume the thread when the user returns to the app in onResume(). The following is the code I've implemented, but it's not working (the onPause(), and onResume() pieces), and I don't understand why. I've read a few other posts on similar matters, but they haven't helped me figure out what to do in my situation. I've read that TimerTasks are outdated, and I should probably use an ExecutorService method; it is unclear to me as how to implement this function.

   ...timerStep5 = new TimerTask() {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                if (b5) {
                    cashButton2SignalText.setBackgroundColor(Color.RED);
                    cashButton2SignalText.setTextColor(Color.WHITE);
                    b5=false;
                } else {
                    cashButton2SignalText.setBackgroundColor(Color.WHITE);
                    cashButton2SignalText.setTextColor(Color.RED);
                    b5=true;
                }
                }
            });
        }
};

timer5.schedule(timerStep5,250,250);

}

public void onPause(){

    super.onPause();

    timerStep5.cancel();

}

public void onResume(){

    super.onResume();

    timerStep5.run();

}
Hanhana answered 15/3, 2013 at 22:38 Comment(1)
Possible duplicate of Pausing/stopping and starting/resuming Java TimerTask continuously?Electroshock
M
15

After a TimerTask is canceled, it cannot run again, you have to create a new instance.

Read details here:

https://mcmap.net/q/88900/-pausing-stopping-and-starting-resuming-java-timertask-continuously

ScheduledThreadPoolExecutor is recommended for newer code, it handles the cases like exceptions and task taking longer time than the scheduled interval.

But for your task, TimerTask should be enough.

Meadow answered 15/3, 2013 at 23:5 Comment(3)
Ok, I saw this post earlier, and was confused with it; maybe you can clarify something for me: a user might leave my app during the TimerTask activity, and return to that activity more than once. Wouldn't that mean I would have to create a new instance of a TimerTask within onResume() every time the user leaves during this activity, and returns?Hanhana
Question: If I were to ignore the action of a user leaving this activity for a moment and returning, and left out any implementation for pausing and resuming the TimerTask, but implemented onStop() to cancel the TimerTask when the user finally moves forward to another activity, would this cause some kind of memory leak while the TimerTask activity is paused?Hanhana
I don't think there will be any memory leak, but it does not make sense to let your UI updating task run in background for nothing. Yes, you're supposed to create TimerTask on the fly and it's not reusable. It's designed this way. (I guess for thread-safety) Also onResume is not some tight loop, the cost of creating an object is negligible.Meadow
F
5

Here's how I did it. Add pauseTimer boolean where ever the pause takes place (button listener perhaps) and don't count timer if true.

private void timer (){
    Timer timer = new Timer();
    tv_timer = (TextView) findViewById(R.id.tv_locationTimer);
    countTimer = 0;
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    String s_time = String.format("%02d:%02d:%02d",
                            countTimer / 3600,
                            (countTimer % 3600) / 60,
                            countTimer % 60);
                    tv_timer.setText(s_time);
                    if (!pauseTimer) countTimer++;
                }
            });
        }
    }, 1000, 1000);
}
Factfinding answered 20/8, 2016 at 0:6 Comment(0)
P
1
Timer timer1;
private boolean timerStartFlag = false;
private boolean hiddenVisibleFrg = false;
int timerSize = 0;
int videoTime = 0;


@Override
public void onPause() {
    super.onPause();

    Log.e("keshav", "onPause timer1 " +timer1);
    if (timerSize >0 &&hiddenVisibleFrg){
        timerStartFlag =true;
    }

    if (timer1 != null) {
        this.timer1.cancel();
    }

}

@Override
public void onResume() {
    super.onResume();

    if (timerSize >0 && timerStartFlag && hiddenVisibleFrg) {
        callTimerTask(timerSize);
        timerStartFlag = false;
    }
}

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);

    if (!hidden) {
        Log.e("keshav", "HomeFragment  visible ");

        if (timerSize >0 && timerStartFlag) {
            callTimerTask(timerSize);
            timerStartFlag=false;
        }

        hiddenVisibleFrg=true;

    } else {
        Log.e("keshav", "HomeFragment in visible " +timer1);
        if (timer1 != null) {
            this.timer1.cancel();
        }
        if (timerSize >0){
            timerStartFlag =true;
        }
        hiddenVisibleFrg=false;
    }
}


private void callTimerTask(int size) {
    // TODO Timer for auto sliding
    printLog("callTimerTask size " + size);
    timer1 = new Timer();
    timer1.schedule(new TimerTask() {
        @Override
        public void run() {
            if (getActivity() != null) {
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (getActivity() == null) {
                            return;
                        }
                        if (count1 < size - 1) {
                            //TODO ADD ME kk
                            count1++;
                        } else {
                            count1 = 0;
                        }
                        if (intro_images != null) {
                            intro_images.setCurrentItem(count1);
                        }
                        videoTime++;
                        Log.e("KeshavTimer", "callTimerTask videoTime " + videoTime);
                    }
                });
            } else {
                printLog("callTimerTask getActivity is null ");
            }
        }
    }, 1000, 1000);
    // TODO  1000, 3000;
}
Parenthood answered 8/8, 2019 at 10:33 Comment(0)
B
1

For Kotlin user, checkout this

How to use:

// Init timer
lateinit var timerExt: CountDownTimerExt

timerExt = object : CountDownTimerExt(TIMER_DURATION, TIMER_INTERVAL) {
    override fun onTimerTick(millisUntilFinished: Long) {
        Log.d("MainActivity", "onTimerTick $millisUntilFinished")
    }

    override fun onTimerFinish() {
        Log.d("MainActivity", "onTimerFinish")
    }

}

// Start/Resume timer
timerExt.start()

// Pause timer
timerExt.pause()

// Restart timer
timerExt.restart()
Burdensome answered 2/11, 2020 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.