removeCallbacks不会停止runnable

cod*_*usa 37 android runnable

我从一个方法调用:

myHandler.postDelayed(mMyRunnableHide, 6000);
Run Code Online (Sandbox Code Playgroud)

哪个叫:

public Runnable mMyRunnableHide = new Runnable()
{

    public void run()
    {
        mTextDisplay.setText("");
        DisplayX();
    }
 };
Run Code Online (Sandbox Code Playgroud)

如果点击屏幕上的按钮,我想停止runnable:

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

            myHandler.removeCallbacks(mMyRunnableHide);

            mTextDisplay.setText("");
            DisplayX();
            }
        });   
    }
Run Code Online (Sandbox Code Playgroud)

removecallbacks不会停止runnable.我究竟做错了什么?我使用的方法是否正确?我只是希望当用户单击按钮时runnable为"Not Run".

谢谢你的帮助.

mtm*_*ock 35

在我看来,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;
   }
}
Run Code Online (Sandbox Code Playgroud)

这只会阻止它启动,但你偶尔可以检查killMe和拯救.如果你正在循环runnable(就像某种后台线程),你可以说:

while(!killMe) {
   /* do work */
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

编辑我只是想发布一个更新.自从这篇原创帖子以来,谷歌已经推出了一个名为AsyncTask的优秀课程,可以为你处理所有这些内容.任何阅读此内容的人都应该深入研究,因为这是正确的做事方式.

你可以在这里阅读它

  • 一定要将killMe标记为"volatile".否则,编译器很可能用`while(true)`替换`while(!killMe)`,因为它永远不会改变(据它所知). (3认同)
  • 错字,MyRunnable"实现"Runnable {...}不是"扩展" (2认同)
  • 当有许多线程访问同一个全局变量时,@ AndyShulman volatile变量最有用.挥发性实际上说的是,"永远不要将这个变量存储在寄存器中.总是从内存中读取它".如果您的代码经常读取/更改变量并且必须在线程间保持准确,这一点就变得非常重要. (2认同)
  • @mtmurdock`removeCallbacks`是同步的,当从主线程调用时立即生效。在主线程中不能同时运行“已开始”回调。如果Runnable正在运行,则按钮处理程序将永远不会运行,直到Runnable完成。如果一切都从主线程调用,则不需要标志。 (2认同)

Mis*_*ith 13

Handler.removeCallback 是同步的,并将很好地提供:

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

所以在你的情况下removeCallbacks从一个按钮处理程序调用,它在主线程中运行.但是你没有在你的代码中显示你打电话的地方postDelayed.如果你从后台线程调用它来解决你的问题所在.

如果你确信你没有调用任何的后台线程中的这些方法,以及调用的顺序是正确的,那么你可能会离开未取消任务unadvertedly活着由于对配置变化的活动娱乐(屏幕旋转等).始终确保removeCallbacksonDestroy方法中再次调用以防止出现此类问题.


Jam*_* L. 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;
}
}
Run Code Online (Sandbox Code Playgroud)