如何在Android中通过按钮点击停止Runnable?

6

我需要在开始按钮点击时启动可运行程序,并在暂停按钮点击时停止它。以下是我在开始按钮点击时启动可运行程序的代码:

    // TODO Auto-generated method stub
    //while (running) {
     mUpdateTime = new Runnable() {
            public void run() { 
     sec += 1;
        if(sec >= 60) {
            sec = 0;
            min += 1;
            if (min >= 60) {
                min = 0;
                hour += 1;
            }
        }
        Min_txtvw.setText(String.format(mTimeFormat, hour, min, sec));
        mHandler.postDelayed(mUpdateTime, 1000);
            }
        };
        mHandler.postDelayed(mUpdateTime, 1000);
    //}

现在我想在暂停按钮点击时停止该可运行对象。

pause_btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            play_btn.setVisibility(View.VISIBLE);
            pause_btn.setVisibility(View.INVISIBLE);

        }
    });

如果有人知道,请告诉我如何在暂停按钮点击时停止该可运行对象。


1
可能是Android:如何停止Runnable?的重复问题。 - patryk.beza
5个回答

15

使用

mHandler.removeCallbacksAndMessages(runnable);

点击暂停按钮。


15
这不会停止正在进行中的操作。 - Gusdor

9

保持一个boolean cancelled标志来存储状态。将其初始化为false,然后在停止按钮的点击上将其修改为true。

在你的run()方法中不断检查这个标志。

编辑

以上方法通常有效,但停止可运行/线程的最合适方法仍然不是这种方式。可能会出现任务被阻塞且无法检查标志的情况,如下所示:

     public void run(){
        while(!cancelled){
           //blocking api call
        }
    }

假设任务正在进行阻塞式的 API 调用并修改了取消标记。只要阻塞式 API 调用还在进行中,任务将无法检查状态的变化。 替代方案和安全方法 最可靠的停止线程或任务(Runnable)的方法是使用 interrupt 机制。中断是一种协作机制,确保停止线程不会使其处于不一致的状态。
在我的博客上,我详细讨论了中断的问题,链接:链接

1
据我所知,这是关闭异步操作的最佳方法。它不是免费的(操作必须轮询标志),但它允许操作以自己的时间结束并清理所有资源。我经常看到的方法只是中止一个线程-这是一种非常危险的做法。请务必继承您自己的Runnable并声明此标志以进行重用! - Gusdor
如果在线程之间不共享任何内容(原始类型、对象等),并在停止时进行清理,则不会出现任何问题。 - stephen

1

完整代码:

   iterationCount = 0;
   final Handler handler = new Handler();
    final int delay = 1000; //milliseconds
    handler.postDelayed(new Runnable() {
        public void run() {
            //do something
            if (iterationCount < 10) {
                handler.postDelayed(this, delay);
            }
            iterationCount++;
            Log.e("tag", "after 1 second: " + iterationCount);
        }
    }, delay);

0
请使用以下代码:

handler.removeCallbacks(runnable);

-2

线程 thread;
//在开始按钮内部

 thread=new Thread(new Runnable() {

    @Override
    public void run() {
    sec += 1;
        if(sec >= 60) {
             sec = 0;
             min += 1;
            if (min >= 60) {
                min = 0;
                hour += 1;
        }
         }
         Min_txtvw.setText(String.format(mTimeFormat, hour, min, sec));
         mHandler.postDelayed(mUpdateTime, 1000);
      });
   thread.start();

//停止按钮内部

mHandler.removeCallbacksAndMessages(runnable);
thread.stop();

1
除了回答问题之外,在您的示例中使用Runnable在Thread内的目的是什么? - Bart Burg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接