nested postDelayed / Runnable / Handler Android

六眼飞鱼酱① 提交于 2019-11-27 06:26:26

问题


I am trying to use a nested postDelayed because I need to do something after (delayed for) 5 minutes, stop it after (delayed) 30 seconds, do something else, then repeat both events in the cycle again from the start. I just can't seem to get it right.

code I have sofar:

private long EnabledAfter  = 300000; // 5 minutes
private long DisabledAfter = 30000;  // 30 seconds

public void start_timers(){
    on_delayed(EnabledAfter);
}//end method

private void on_delayed(long period_off){       
    Delayed = new Runnable() {
        public void run() {                                                     
            something.enable(context);                          
            something.enable_else(context, true);       
            off_delayed(DisabledAfter); // and disable both again delayed

            Handler.postDelayed(Delayed, EnabledAfter);
        }
    };
    Handler.postDelayed(Delayed, EnabledAfter);
}//end method

private void off_delayed(long period_on){       
    Delayed = new Runnable() {
        public void run() {
            something.disable(context);                                 
            something.disable_else(context, false); 
            on_delayed(period_on); // start the proces again from the start...

            //Handler.postDelayed(Delayed, DisabledAfter);              
        }
    };
    Handler.postDelayed(Delayed, period_on);
}//end method

The problem with this is runs fine the first run, but then seems to stack on top of each other...and all delays are borked. I need to execute the both Runnables in exactly 5 minutes and 30 seconds, then repeat the process.


回答1:


The net result after this code has run a few times is that the Handler posts way too many instances of each Runnable. As written above:

  1. First on_delayed posts 1 Runnable
  2. That runnable fires and then posts 2 Runnables (one in off_delayed, and another before returning from run()).
  3. This will continue to multiply because when those two Runnables fire, 4 will get created, an so on.

You are also not taking advantage of the fact that a Runnable can be posted to the same queue multiple times, it doesn't have to be created new each time. This is essential if you want to cancel the actions, because the remove method on Handler look for all the matching instances to remove from the queue. You might try something like this instead:

private long EnabledAfter  = 300000; // 5 minutes
private long DisabledAfter = 30000;  // 30 seconds

private Runnable Enabler = new Runnable() {
    public void run() {                                                     
        something.enable(context);                          
        something.enable_else(context, true);       

        Handler.postDelayed(Disabler, DisabledAfter);
    }
};

private Runnable Disabler = new Runnable() {
    public void run() {
        something.disable(context);                                 
        something.disable_else(context, false); 

        Handler.postDelayed(Enabler, EnabledAfter);              
    }
};

public void start_timers(){
    Handler.postDelayed(Enabler, EnabledAfter);
}//end method

public void stop_timers(){
   Handler.removeCallbacks(Enabler);
   Handler.removeCallbacks(Disabler);
}//end method

I also added one more method you can use to cancel the timer operation by removing all the instances of your Runnable items from the queue.

HTH



来源:https://stackoverflow.com/questions/11197543/nested-postdelayed-runnable-handler-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!