Как я могу передать переменную в postdelayed runnable?

#java #runnable #postdelayed

#java #выполняемый #postdelayed

Вопрос:

Я создал два класса, реализованных из runnable(). Затем я вызываю их несколько раз, с разной задержкой. Проблема в том, что когда я запускаю runnable позже, он должен знать значение переменной еще при вызове postdelay, а не при ее фактическом запуске.

Я думаю, что теперь мне нужно сделать, это передать переменную в экземпляр runnable при вызове post delay. Но, хоть убей, я не могу понять, как это сделать. Вот исходный код для справки:

 public void PlaySequence() throws InterruptedException{

for(int i = 0;i<level;i  ){
    mHandler.postDelayed(mToggleButtonOn, (i 1)*playbackOffTime);
    mHandler.postDelayed(mToggleButtonOff, (i 1)*playbackOnTime);           
    currentProgIteration  ;
}        
currentProgIteration=0;     
}

private Runnable mToggleButtonOn = new Runnable() {

public void run() {
    try {
            if(Sequence[currentProgIteration]==0){
                ImageCard[0].setImageDrawable(getResources().getDrawable(R.drawable.yellow));
            }
            else if(Sequence[currentProgIteration]==1){
                ImageCard[1].setImageDrawable(getResources().getDrawable(R.drawable.blue));
            }
            else if(Sequence[currentProgIteration]==2){
                ImageCard[2].setImageDrawable(getResources().getDrawable(R.drawable.red));
            }
            else if(Sequence[currentProgIteration]==3){
                ImageCard[3].setImageDrawable(getResources().getDrawable(R.drawable.green));
            }                   
        }
     catch (IllegalStateException e) {
        e.printStackTrace();
    }

}
};

private Runnable mToggleButtonOff = new Runnable() {

public void run() {
    Log.d("Info", "running Off currentProgIteration: " currentProgIteration);

    try {
            if(Sequence[currentProgIteration]==0){
                ImageCard[0].setImageDrawable(getResources().getDrawable(R.drawable.darkyellow));
            }
            else if(Sequence[currentProgIteration]==1){
                ImageCard[1].setImageDrawable(getResources().getDrawable(R.drawable.darkblue));
            }
            else if(Sequence[currentProgIteration]==2){
                ImageCard[2].setImageDrawable(getResources().getDrawable(R.drawable.darkred));
            }
            else if(Sequence[currentProgIteration]==3){
                ImageCard[3].setImageDrawable(getResources().getDrawable(R.drawable.darkgreen));
            }                   
        }
    catch (IllegalStateException e) {
        e.printStackTrace();
    }

}
};
 

Исполняемые файлы используют глобальную переменную currentProgIteration, но к моменту их запуска после задержки эта переменная была возвращена к 0.

Спасибо за любой совет.

Ответ №1:

Самым простым подходом может быть использование анонимного Runnable.

 final int delay = (i 1)*playbackOffTime;
mHandler.postDelayed(new Runnable() {
   final Color[] colours = { R.drawable.yellow, R.drawable.blue, R.drawable.red, R.drawable.green } ;
   public void run() {
        try {
           // can use "delay" here
           int seq = Sequence[currentProgIteration];
           ImageCard[seq].setImageDrawable(getResources().getDrawable(colours[seq]));
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }
});
 

Комментарии:

1. Есть ли какой-нибудь способ использовать это и при этом иметь возможность вызвать ‘removeCallbacks (…)’, чтобы отменить анонимный запускаемый? Я не могу этого понять.

2. @CoryTrese Уверен, что mHandler поддерживает это. Если вы используете ExecutorService, он возвращает будущее, которое может быть отображено cancel() .

Ответ №2:

Как сказал Питер, вы можете использовать anonymous Runnable

чтобы сделать возможным removeCallbacks(…), вы могли бы удалить runnables с помощью токена:

создайте токен верхнего уровня для отдельных Runnables, размещенных в MessageQueue, например

val animToken = Any()

для того, чтобы отслеживать ваш runnable, используйте следующее расширение:

 fun Handler.postDelayedWithToken(token: Any, delayInMillis: Long, runnable: Runnable) {
    postAtTime(runnable, token, SystemClock.uptimeMillis()   delayInMillis)
}
 

пример использования:
handler.postDelayedWithToken(animToken, 3000L, { hideSomething() })

для того, чтобы утилизировать (например: перед onPause / onStop / onDestroyView):

handler.removeCallbacksAndMessages(animToken)