40

我从一个方法调用:

myHandler.postDelayed(mMyRunnableHide, 6000);

调用:

public Runnable mMyRunnableHide = new Runnable()
{

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

如果单击屏幕上的按钮,我想停止可运行:

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

            myHandler.removeCallbacks(mMyRunnableHide);

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

removecallbacks 不会停止可运行的。我究竟做错了什么?我使用正确的方法吗?当用户单击按钮时,我只希望可运行对象“不运行”。

谢谢你的帮助。

4

5 回答 5

36

在我看来,removeCallbacks(..)这只停止待处理的消息(Runnables)。如果您的 runnable 已经开始,那么就没有停止它(至少不是这样)。

或者,您可以扩展 Runnable 类并为其提供某种终止开关,如下所示:

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

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

      /* do your work */
   }

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

这只会阻止它启动,但您可以偶尔检查killMe并退出。如果您正在循环运行可运行文件(例如某种后台线程),您可以说:

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

希望这可以帮助

编辑我只是想发布有关此的更新。自从这篇原始文章以来,Google 提出了一个名为 AsyncTask 的出色类,它可以为您处理所有这些事情。任何阅读本文的人都应该仔细研究它,因为它是正确的做事方式。

你可以在这里阅读

于 2011-04-30T20:29:34.570 回答
14

Handler.removeCallback是同步的,并且可以很好地工作:

  1. postDelayed总是在主线程中调用。
  2. removeCallback总是在主线程中调用
  3. postDelayed删除回调后,您不会再次调用。

因此,在您的情况下removeCallbacks,是从在主线程中运行的按钮处理程序调用的。但是您没有在代码中显示您调用的点postDelayed。如果您从后台线程调用它,那就是您的问题所在。

如果您确定没有从后台线程调用这些方法中的任何一个,并且调用的顺序是正确的,那么由于配置更改(屏幕旋转等)的活动重新创建,您可能会无意中留下未取消的任务。始终确保removeCallbacks在方法中再次调用onDestroy以防止出现此类问题。

于 2016-03-15T16:04:25.380 回答
7

这是完成 mtmurdock 描述的另一种方法。此类将允许在 Runnable 定义为匿名内部类的任何类中编辑实例变量。

package support;

/**
* Runnable that can be stopped from executing
*/
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;
}
}
于 2015-02-20T17:54:06.503 回答
0

我不认为 removeCallbacks(..) 只会停止挂起的消息 (Runnables) ,我认为 removeCallbacks(..) 不起作用有其他原因,但我不知道。因为 postDelayed(..) 和 removeCallbacks(..) 在同一个线程中

于 2018-06-29T09:40:09.673 回答
0

以下对我有用。将其放在 onResume 中。

mService= null;

public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i(TAG, "OnServiceConnected");
        ContadorFG.LocalBinder binder = (ContadorFG.LocalBinder) service;
        mService = binder.getService();
        connected = true;
        synchronized (lock){
            lock.notifyAll();
        }
    }

public void onResume() {
    super.onResume();
    loopDelayed();
}  

private void loopDelayed(){ 
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (mService != null) {

                ----
                ----
                ----

                return;
            }else{
                //auto call 
                loopDelayed();
            }
        }
    }, 10);

}
于 2020-04-18T19:17:02.767 回答