【问题标题】:Pausing timer without destroy and re-create - Android暂停计时器而不销毁和重新创建 - Android
【发布时间】:2015-07-15 23:22:38
【问题描述】:

我有这个 AsyncTask,每次执行“doInBackground”时睡眠 0.1 秒,在此之前我使用 CountDownTimer 来控制我的时间。

我的问题是:我想实现一个可以暂停而不调用.cancel() 以及何时开始创建另一个计时器的计时器。

有没有办法实现这个是android?我没有找到如何以不同的方式做到这一点。你能举个例子吗?

我在哪里找到了取消计时器的示例:

编辑

回答Kevin Krumwiede:这个项目是一种游戏,我必须在确定的时间内击中块,所以我想实现一种方法,当玩家使用某种特殊力量时停止计时器(点击指定的按钮)。

EDIT2

Answering Kushal:我不知道你有没有编译过这段代码,但是我不能使用 task1 变量。代码如下:

   public void doIt(){
        final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();

        final Runnable task =
        new Runnable() {

            @Override
            public void run() {
                timerAsyncTask.execute();

                if(true) {
                    exec.shutdown();    // shutdown this execution
                    //exec = Executors.newSingleThreadScheduledExecutor();
                    exec.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS);
                }
            }
        };
        exec.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS);
    }

这里exec = Executors.newSingleThreadScheduledExecutor(); 显示一个错误:

错误:(33, 21) 错误: 无法为最终变量 exec 赋值

我认为这很好,一旦 exec 是最终变量。

这里exec.scheduleAtFixedRate(task, 0, 100, TimeUnit.MILLISECONDS);我又遇到了一个错误:

Error:(34, 46) 错误:变量任务可能没有被初始化

你能解释一下,我该如何使用这段代码?我对android很陌生。 谢谢。

【问题讨论】:

  • 几乎没有充分的理由在 Android 中使用 Timer。告诉我们更多关于您的用例,也许我们可以提出更合适的解决方案。
  • 我已经编辑了问题。

标签: android timer countdowntimer timertask onpause


【解决方案1】:

我建议您完全避免使用 Android 中的计时器。 Android 有一个轻量级和更好的解决方案,称为Handler

您可以找到这两个here 之间的比较。总结一下

比较处理程序与计时器

  • 虽然重新调度 Handler 很容易,但不能重新调度 Timer
  • 在 Handler 中,您可以附加到任何 Runnable 但 Timer 计划仅用于 一个 TimerTask
  • TimerTask 是纯后台任务,所以不能更新 UserInterface,但对于 Handler 的 Runnables 而言并非如此
  • 计时器导致执行
  • 与 Handler 相比,Timer 倾向于泄漏更多内存,请参见图表 对象由计时器和处理程序保留。它将迅速增加 如果您正在创建和安排新任务,请使用计时器。

正如帖子所暗示的,处理程序的使用非常简单。这是一个示例代码

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;

public class TestActivity extends AppCompatActivity {


    private static int INITIAL_TIMER_DELAY = 100;
    private static int TIMER_PERIOD = 100;

    private android.os.Handler handler;
    private Runnable runnable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        handler = new Handler(Looper.getMainLooper());
        runnable = new Runnable() {
            @Override
            public void run() {
                // Do something and reschedule ourself
                handler.postDelayed(this, TIMER_PERIOD);
            }
        };
        handler.postDelayed(runnable, INITIAL_TIMER_DELAY);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cancelTimer();
    }

    private void cancelTimer() {
        if (handler != null) {
            handler.removeCallbacks(runnable);
        }
    }

    private void rescheduleRunnable() {
        handler.postDelayed(runnable, INITIAL_TIMER_DELAY)
    }


}

【讨论】:

    【解决方案2】:

    您可以使用 ScheduledExecutorService 类实现您的要求

    ScheduledExecutorServiceTimer 类的基本区别是:

    • 使用 Timer 类,您无法检查执行情况。您可以开始和停止执行,但不能根据条件检查执行
    • ScheduledExecutorService 提供了在启动和停止调用之间检查执行情况的方法。如果任务的任何执行遇到异常,后续执行将被抑制

    我们如何满足您的要求:

    • doInBackground() 执行之间需要 0.1 秒的延迟
    • 当其他执行开始时,我们将能够暂停我们的执行

      ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
      
      Runnable task1 = new Runnable() {
        public void run() {
          // start your AsyncTask here
          new <your_task>().execute();
      
          if (<check_your_condition_when_to_pause>) {
            exec.shutdown();    // shutdown this execution 
            exec = Executors.newSingleThreadScheduledExecutor();
            exec.scheduleAtFixedRate(task1, 0, 100, TimeUnit.MILLISECONDS);
            // here i have passed task1 for example
            // here we need to pass next task runnable which
            // we want to run after 0.1 seconds
          } else {
            // continue normal
          }
      
        }
      };
      
      exec.scheduleAtFixedRate(task1, 0, 100, TimeUnit.MILLISECONDS);
      

    信用参考:Answer 1Answer 2

    我希望这将有助于解决您的一些疑问

    【讨论】:

    • 当您从 declarayion 中删除 final 时,第一个错误将被删除。对于第二个错误,请声明 Runnable task = null;,然后调用 new 运算符 task = new Runnable() {
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    相关资源
    最近更新 更多