Android计时器无法停止

14
问题
在安卓开发中,我无法停止定时器。
当我尝试停止定时器时,它已经是null了。
我将定时器初始化移动到方法之外,与TimerTask一样,解决了null的问题,但仍然无法通过timer.cancel();来取消定时器。
下面的代码是一个例子,当尝试停止录音时,定时器已经是null。 TimerTask
我的TimerTask在类内被初始化,但在方法外,代码如下...
private TimerTask task = new TimerTask() {
    @Override
    public void run() {
      Log.e("TRACK_RECORDING_SERVICE","Timer Running");
    }
  };

计时器和计时器启动

当我想要启动计时器时,我会调用一个名为startRecording的方法...

public void startRecording(){
     timer = new Timer("Message Timer");
     timer.scheduleAtFixedRate(this.task, 0, 1000);
 }

定时器停止

当我想要停止计时器时,我调用以下方法...

public void stopRecording() {
     if (timer != null) {
         timer.cancel();
         timer = null;
     } else {
         Log.e("TRACK_RECORDING_SERVICE","Timer already null.");
     }
 }

非常感谢任何帮助。


1
你尝试过使用 task.cancel() 后跟 timer.purge() 吗? - Steelight
9个回答

23
timer = new Timer("Message Timer"); 

在这里,你的对象timer不是一个static,因此timer.cancel();会取消另一个Timer类的实例。我建议您在类的顶部创建一个静态的Timer Class实例变量,如下所示:

private static Timer timer;

6
我创建了静态实例,但它仍然不会停止。 - asiya
是的,我也创建了静态实例,它不会停止 :) - bebosh
我不明白将引用设为静态有什么帮助。cancel() 是在由 timer 引用的 Timer 上调用的,为什么它会被用于另一个实例? - Leo supports Monica Cellio
我不知道,但它有效。可能是因为“static”使属性对于该类唯一,即该属性的所有实例仅有一个实例。然而,我不知道为什么会有多个实例。 - Maxouille
它对我不起作用。即使我只创建了一个实例,它也无法工作。 - Maulik Patel

3
在run()方法中,检查计时器是否为空,然后...

private TimerTask task = new TimerTask() {
@Override
public void run() {
if (timer == null)
 cancel();
...
}

取消操作。

2

好的,问题出在实例化而不是实际停止计时器上。

每次我调用:

Original Answer

翻译成:

最初的回答

timer = Timer()
timer!!.scheduleAtFixedRate(object : TimerTask() {
    override fun run() {
       //something  
    }
}, delay, period)

它创建了另一个实例,因此旧实例仍在某处运行,无法停止。

所以我只是确保在计时器为null时进行实例化,这样就不会推动以前的实例并在后台继续运行。

Original Answer翻译成"最初的回答"

if(timer == null) {
    timer = Timer()
    timer!!.scheduleAtFixedRate(object : TimerTask() {
        override fun run() {
            // something
        }
    }, delay, period)
}

那就取消它并将其设置为null吧。最初的回答。
fun stopTimer() {
    if (timer != null) {
        timer!!.cancel()
        timer!!.purge()
        timer = null
    }
}

1

我知道现在已经很晚了,但我在我的项目中也遇到了这个问题,希望我的解决方案能给人们一些启示。我在我的项目中所做的如下:

Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
           //TODO Update UI
        }
    };

    public void stopTimer() {
        if (timer != null) {
            handler.removeCallbacks(runnable);
            timer.cancel();
            timer.purge();
            timer = null;
        }
    }

   public startTimer() {
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    handler.post(runnable);
                }
            }, 0, 100);
       }

我认为之前的回答中遗漏了removeCallbacks

1
if(waitTimer != null) {
   waitTimer.cancel();
   waitTimer.purge()
   waitTimer = null;
}

0

如果有人仍然在这里寻找解决此问题的方法,这是我的经验。

我正在服务中运行一个计时器。

startForegroundService(mServiceIntent);

timer = new Timer();

当您刷新服务时,不一定需要先取消它,只需再次调用startForegroundService(mServiceIntent)即可。

如果在刷新服务之前不取消计时器,则原始计时器仍在后台运行并调用方法,即使您在刷新的新服务中停止了计时器。

因此,在刷新或更新后台任务之前,请停止计时器。

希望对某些人有所帮助。


0

我觉得你取消了另一个定时器实例。

你的定时任务最好由一个辅助类来处理。

public class TimerHelper {
    Timer timer;
    long InitialInMillis = 10 * 1000;
    long DelayInMillis = 2 * 60 * 1000; // 2 minutes

    public TimerHelper() {
        timer = new Timer();
        timer.schedule(new MyTimerTask(), InitialInMillis, DelayInMillis);
    }

    public void stopTimer() {
        if(timer != null){
            timer.cancel();
        }
    }

    class MyTimerTask extends TimerTask {
        @Override
        public void run() {
            // your task will be run every 2 minutes
            yourTask();
        }
    }
}

0

试一下这个例子……

     TimerTask mTimerTask;
    final Handler handler = new Handler();
    Timer t = new Timer();  
    int nCounter = 0;

//function for start timer
 public void doTimerTask()
    {

        mTimerTask = new TimerTask() 
        {
                public void run() 
                {
                        handler.post(new Runnable() 
                        {
                                public void run()
                                {

                                      nCounter++:       
                                    //your code
                                    .....
                                    ......

                                }
                       });
                }};

            // public void schedule (TimerTask task, long delay, long period) 
            t.schedule(mTimerTask,0,50);  // 

         }

         //function for stop timer
public void stopTimerTask(){

       if(mTimerTask!=null){

          Log.d("TIMER", "timer canceled");
          mTimerTask.cancel();
          nCounter = 0; 

     }

}    

//使用上述两个函数来启动和停止计时器。


0

虽然这是一个老问题,但我已经找到了一个简单的解决方案。

var timeTaskInstance : TimerTask ?= null

val task: TimerTask = object : TimerTask() {
      override fun run() {
           timeTaskInstance = this
           Log.e("TRACK_RECORDING_SERVICE", "Timer Running")
      }
 }

现在可以从任何地方取消计时器:

timeTaskInstance?.cancel()

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