#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)