вложенный postDelayed/Runnable/Handler Android

Я пытаюсь использовать вложенный postDelayed, потому что мне нужно что-то сделать через (отложено) 5 минут, остановить его через (отложено) 30 секунд, сделать что-то еще, а затем снова повторить оба события в цикле с самого начала. Я просто не могу понять это правильно.

код у меня софа:

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

Проблема с этим заключается в том, что первый запуск выполняется нормально, но затем кажется, что они накладываются друг на друга... и все задержки прерываются. Мне нужно выполнить оба Runnable ровно за 5 минут и 30 секунд, а затем повторить процесс.


person slinden77    schedule 25.06.2012    source источник


Ответы (1)


Конечным результатом после нескольких запусков этого кода является то, что Handler публикует слишком много экземпляров каждого Runnable. Как написано выше:

  1. Первые сообщения on_delayed 1
  2. Этот runnable срабатывает, а затем отправляет 2 Runnables (один в off_delayed, а другой перед возвратом из run()).
  3. Это будет продолжать размножаться, потому что, когда эти два Runnables сработают, будет создано 4 и так далее.

Вы также не пользуетесь тем фактом, что Runnable можно отправлять в одну и ту же очередь несколько раз, его не нужно каждый раз создавать заново. Это важно, если вы хотите отменить действия, потому что метод удаления на Handler ищет все соответствующие экземпляры для удаления из очереди. Вместо этого вы можете попробовать что-то вроде этого:

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

Я также добавил еще один метод, который вы можете использовать для отмены операции таймера, удалив все экземпляры ваших Runnable элементов из очереди.

ХТН

person devunwired    schedule 25.06.2012
comment
ммм, спасибо, это работает! Почему, почему я не подумал об этом? Спасибо за помощь! - person slinden77; 26.06.2012
comment
Я приветствую вас, сэр. Это то, о чем я сам не мог подумать. Я использовал ваш пример, чтобы создать один исполняемый файл для анимации с закрытым оператором switch, и он работает как шарм! - person Danny E.K. van der Kolk; 16.02.2021