Подтвердить что ты не робот

RemoveCallbacks не останавливается

Я звоню из метода:

myHandler.postDelayed(mMyRunnableHide, 6000);

который вызывает:

public Runnable mMyRunnableHide = new Runnable()
{

    public void run()
    {
        mTextDisplay.setText("");
        DisplayX();
    }
 };

Если нажата кнопка на экране, я хочу остановить runnable:

   Button next = (Button) findViewById(R.id.Breaction);
    next.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

            myHandler.removeCallbacks(mMyRunnableHide);

            mTextDisplay.setText("");
            DisplayX();
            }
        });   
    }

removeecallbacks не останавливает runnable. Что я делаю не так? Использую ли я правильный метод? Я просто хочу, чтобы runnable "Not Run", когда пользователь нажимает кнопку.

Спасибо за любую помощь.

4b9b3361

Ответ 1

Мне кажется, что removeCallbacks(..) останавливает только ожидающие сообщения (Runnables). Если ваш runnable уже запущен, то нет его остановки (по крайней мере, не так).

В качестве альтернативы вы можете расширить класс Runnable и дать ему своего рода kill-переключатель следующим образом:

public class MyRunnable implements Runnable
{
   private boolean killMe = false;

   private void run()
   {
      if(killMe)
         return;

      /* do your work */
   }

   private void killRunnable()
   {
      killMe = true;
   }
}

Это только предотвратит его запуск, но вы можете иногда проверять killMe и выходить из системы. Если вы зацикливаете runnable (например, какой-то фоновый поток), вы можете сказать:

while(!killMe) {
   /* do work */
}

Надеюсь, что это поможет

EDIT Я просто хотел опубликовать обновление об этом. Начиная с этого оригинального сообщения, Google придумал отличный класс под названием AsyncTask, который обрабатывает все эти вещи для вас. Любой, кто это читает, должен смотреть на него, потому что это правильный способ делать вещи.

Вы можете прочитать об этом здесь

Ответ 2

Вот еще один способ выполнить то, что описывает mtmurdock. Этот класс позволит редактировать переменные экземпляра в любом классе, чтобы ваш Runnable был определен как анонимный внутренний класс.

package support;

/**
* Runnable that can be stopped from executing
* @author JTRONLABS
*/
public abstract class KillableRunnable implements Runnable{

private boolean isKilled=false;

/**
 * Instead of Overriding run(), override this method to perform a Runnable operation. 
 * This will allow editing instance variables in the class that this Runnable is defined
 */
public abstract void doWork();

//The handler that posts this Runnable will call this method. 
//By default, check if it has been killed. doWork() will now be the method 
//override to implement this Runnable
@Override
final public void run(){
    if(!isKilled){
        doWork();
    }
}

final public void kill(){
    isKilled=true;
}
}

Ответ 3

Handler.removeCallback является синхронным и будет хорошо работать:

  • Вы вызываете postDelayed всегда в основном потоке.
  • Вы вызываете removeCallback всегда в основной поток
  • Вы не вызываете postDelayed снова после удаления обратных вызовов.

Итак, в вашем случае removeCallbacks вызывается из обработчика кнопок, который запускается в основном потоке. Но вы не указали в своем коде точку, где вы называете postDelayed. Если вы вызываете это из фонового потока, где ваша проблема.

Если вы уверены, что вы не вызываете какие-либо из этих методов из фоновых потоков, а порядок вызовов корректен, вы можете оставить незаписанные задачи незарегистрированными из-за активного отдыха при изменениях конфигурации (поворот экрана и т.д.).). Всегда обязательно вызывайте removeCallbacks снова в методе onDestroy, чтобы предотвратить такие проблемы.