4

I have this AsyncTask, that sleeps 0.1 second each time that executes "doInBackground", before that I was using a CountDownTimer to control my time.

My problem is: I want to achieve a timer that can Pause without calling .cancel() and when starts creating another timer.

Is there a way to achieve this is android? I didn't found how to do it in a different way. Can you example it?

Where I've found examples canceling the timer:

EDIT

Answering Kevin Krumwiede: This project is a kind of game, that I must hit blocks in a determinated time, so I want to achieve a way to stop the timer when the player use some kind of special power (hit a button specified).

EDIT2

Answering Kushal: I don't know if you have compiled this code, but I can't use the task1 variable. Here goes the code:

   public void doIt(){
        final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();

        final Runnable task =
        new Runnable() {

            @Override
            public void run() {
                timerAsyncTask.execute();

                if(true) {
                    exec.shutdown();    // shutdown this execution
                    //exec = Executors.newSingleThreadScheduledExecutor();
                    exec.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS);
                }
            }
        };
        exec.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS);
    }

Here exec = Executors.newSingleThreadScheduledExecutor(); it shows me an error:

Error:(33, 21) error: cannot assign a value to final variable exec

What I think it's pretty okay, once the exec is a final variable.

And here exec.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS); I got another error:

Error:(34, 46) error: variable task might not have been initialized

Can you explain, how can I use this piece of code? I'm quite new to android. Thanks.

Community
  • 1
  • 1
guisantogui
  • 4,017
  • 9
  • 49
  • 93
  • 1
    There is almost never a good reason to use `Timer` in Android. Tell us more about your use case and maybe we can suggest a more appropriate solution. – Kevin Krumwiede May 06 '15 at 02:32

2 Answers2

2

You can achieve your requriment using ScheduledExecutorService class

Basic difference between ScheduledExecutorService and Timer class is :

  • Using Timer class, you cannot check how your execution is going. You can start and stop execution but cannot check execution based on condition
  • ScheduledExecutorService provides way to check how execution is running in between start and stop call. If any execution of the task encounters an exception, subsequent executions are suppressed

How we can achieve your requirement :

  • We need 0.1 second delay between doInBackground() execution
  • We shall be able to pause our execution when other execution starts

    ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    
    Runnable task1 = new Runnable() {
      public void run() {
        // start your AsyncTask here
        new <your_task>().execute();
    
        if (<check_your_condition_when_to_pause>) {
          exec.shutdown();    // shutdown this execution 
          exec = Executors.newSingleThreadScheduledExecutor();
          exec.scheduleAtFixedRate(task1, 0, 100, TimeUnit.MILLISECONDS);
          // here i have passed task1 for example
          // here we need to pass next task runnable which
          // we want to run after 0.1 seconds
        } else {
          // continue normal
        }
    
      }
    };
    
    exec.scheduleAtFixedRate(task1, 0, 100, TimeUnit.MILLISECONDS);
    

Credit reference : Answer 1 and Answer 2

I hope this will help to solve some of your doubts

Community
  • 1
  • 1
Kushal
  • 8,100
  • 9
  • 63
  • 82
  • First error will remove when you remove `final` from declarayion.. For second error, declare `Runnable task = null;` and then call `new` operator `task = new Runnable() {` – Kushal May 09 '15 at 05:09
2

I suggest you avoid Timers in Android altogether. Android has a light weight and better solution called Handler

You can find a comparison between these two here. To sum up

Comparison Handler VS Timer

  • While rescheduling Handler is very easy, you can not reschedule Timer
  • In Handler you can attach to any Runnable but Timer schedule for only one TimerTask
  • TimerTask is purely background task so you can not update UserInterface, but that's not true for Handler's Runnables
  • Timer Causes Execptions
  • Timer tends to leak more memory compare to Handler see the graph of object retains by timer and Handler. It will increase rapidly for Timer if you are creating and scheduling new task.

As the post suggests, the Handler usage is pretty simple. Here is an example code

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;

public class TestActivity extends AppCompatActivity {


    private static int INITIAL_TIMER_DELAY = 100;
    private static int TIMER_PERIOD = 100;

    private android.os.Handler handler;
    private Runnable runnable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        handler = new Handler(Looper.getMainLooper());
        runnable = new Runnable() {
            @Override
            public void run() {
                // Do something and reschedule ourself
                handler.postDelayed(this, TIMER_PERIOD);
            }
        };
        handler.postDelayed(runnable, INITIAL_TIMER_DELAY);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cancelTimer();
    }

    private void cancelTimer() {
        if (handler != null) {
            handler.removeCallbacks(runnable);
        }
    }

    private void rescheduleRunnable() {
        handler.postDelayed(runnable, INITIAL_TIMER_DELAY)
    }


}
Bojan Kseneman
  • 15,488
  • 2
  • 54
  • 59