Search code examples
javaandroidservicetimerhandler

Unable to stop/update handler (removeCallbacksAndMessages)


I've implemented an service which cyclically updates the UI at a custom interval. When changing the update interval, I want to stop the current handler and start over with the new interval. As i read in other Threads before, it is not possible to interrupt a handler, after it has been fired. However the solutions mentioned, like removing callbacks and messages

        handler.removeCallbacksAndMessages(null);
        handler.removeCallbacks(runnable);

such as implementing a kill switch

   started = false;
   if(started) {
      //do work..
   }

did not help at all. When I restart my service with an updated interval, the handlers do not stop, causing multiple handlers running at the same time.

Does somebody know what I'm doing wrong or how to to better? Appreciate any help! Thanks!

//Mainactivity
  startService(new Intent(this, updateService.class));


public class updateService extends IntentService {

    private boolean started = false;
    private Handler handler = new Handler();


    public updateService() {
        super("updateService");
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            // Try to stop handler when startservice is called and start new one afterwards 
            stop();
            start();
        return super.onStartCommand(intent, flags, startId);
    }

    public void start() {
        started = true; // Didn't help

        int timer = config_store.getPreference("refresh_interval"));
        if (timer !=0){
            handler.postDelayed(runnable, timer);
        }
        else {
            stop();
        }

    }

 public void stop() {

        started = false;
        handler.removeCallbacksAndMessages(null); // Didn't help
        handler.removeCallbacks(runnable);  // Didn't help
    }

 private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if(started) {  // Didn't help.
                // Update job
                doJob();

                // Start over again
                start();
            }
        }
    };

}

Solution

  • Ok, fixed it myself: delayed handler was not the best solution for cyclically calling methos. Now using TimerTask:

      public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    
            if(mTimer != null) {
                mTimer.cancel();
            }
            mTimer = new Timer();
    
            int timer = Integer.parseInt(getPreference("refresh_interval")) * 1000;
            mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), timer, timer);
            return super.onStartCommand(intent, flags, startId);
        }
    
        class TimeDisplayTimerTask extends TimerTask {
    
            @Override
            public void run() {
                // run on another thread
                mHandler.post(new Runnable() {
    
                    @Override
                    public void run() {
                       // Do job
                    }
                });
            }   
    }