【问题标题】:How to set a timer in android如何在android中设置计时器
【发布时间】:2009-12-09 22:35:52
【问题描述】:

在 android 中设置计时器以启动任务(我创建的一个不会更改 UI 的函数)的正确方法是什么? 使用 Java 方式: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html

或者在android(android的处理程序)中有更好的方法?

【问题讨论】:

    标签: android


    【解决方案1】:

    是的,java 的计时器可以使用,但是问题要求更好的方式(对于移动设备)。这是Here的解释。


    为了 StackOverflow:

    由于Timer 创建了一个新线程,它可能被认为很重,

    如果您只需要在活动运行时获得回调,Handler 可以与

    结合使用

    Runnable

    private final int interval = 1000; // 1 Second
    private Handler handler = new Handler();
    private Runnable runnable = new Runnable(){
        public void run() {
            Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
        }
    };
    ...
    handler.postAtTime(runnable, System.currentTimeMillis()+interval);
    handler.postDelayed(runnable, interval);
    

    Message

    private final int EVENT1 = 1; 
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {         
            case Event1:
                Toast.makeText(MyActivity.this, "Event 1", Toast.LENGTH_SHORT).show();
                break;
    
            default:
                Toast.makeText(MyActivity.this, "Unhandled", Toast.LENGTH_SHORT).show();
                break;
            }
        }
    };
    
    ...
    
    Message msg = handler.obtainMessage(EVENT1);
    handler.sendMessageAtTime(msg, System.currentTimeMillis()+interval);
    handler.sendMessageDelayed(msg, interval);
    

    附带说明,如果您想在 UI 线程中从另一个线程运行一段代码,则可以使用这种方法。

    如果您需要回电,即使您的活动没有运行,您可以使用AlarmManager

    【讨论】:

    • 更新了链接,说说google在维护链接上有问题。
    • 这篇 2007 年的文章 - 并不是说​​它是错误的,但我总是对超过 3 年的移动文章持怀疑态度。事情变化很快。
    • 如果您可以在答案中引用链接的要点,它会更像 StackOverflow。
    • @naxa,我的两分钱让这个回复更像 StackOverflow。
    • 只是一个注释,导入android.os.Handler,而不是java.util.logging
    【解决方案2】:

    通过java.util.Timerjava.util.TimerTask 使用定时器的标准Java 方法在Android 中运行良好,但您应该注意此方法会创建一个新线程。

    您可以考虑使用非常方便的Handler 类(android.os.Handler)并通过sendMessageAtTime(android.os.Message, long)sendMessageDelayed(android.os.Message, long) 向处理程序发送消息。收到消息后,您可以运行所需的任务。第二种选择是创建一个Runnable 对象并通过处理程序的函数postAtTime(java.lang.Runnable, long)postDelayed(java.lang.Runnable, long) 对其进行调度。

    【讨论】:

    • 这是在 android 中做事的错误方式。在 android 中,您希望使用警报管理器 (developer.android.com/reference/android/app/AlarmManager.html) 来运行未来的任务。
    • @Kurtis Nusbaum 这个问题并没有说明任务的未来有多远。
    • @KurtisNusbaum 这不一定是真的,这取决于上下文。 AlarmManager 上的文档说:“注意:Alarm Manager 旨在用于您希望在特定时间运行应用程序代码的情况,即使您的应用程序当前没有运行。对于正常的计时操作(滴答声、超时等)使用 Handler 更简单、更高效。”
    • @Scienceprodigy 啊,我明白了。很公平。
    • 使用 Handler 方法调度任务只有在应用程序获得了 wakeLock 并且因此您确定手机不会进入睡眠状态时才是可靠的。如果手机确实进入睡眠状态,则 sendMessageDelayed 和 sendMessageAtTime 将不起作用。因此,在这种情况下,AlarmManager 将是可靠的选择。
    【解决方案3】:

    正如我所见,java.util.Timer 是最常用于实现计时器的。

    对于重复任务:

    new Timer().scheduleAtFixedRate(task, after, interval);
    

    单次运行任务:

    new Timer().schedule(task, after);
    


    任务是要执行的方法
    初始执行时间之后
    interval重复执行的时间)

    【讨论】:

    • 我只是补充一点,时间是以毫秒为单位的
    • scheduleAtFixedRate 的 Android 开发文档
    • task 可能是您的类的一个实例,它继承自 java.util.TimerTask 并覆盖 void run()
    • 这么多的赞成票。你可以做到这一点。但是@Samuel 描述了更好的方法。有关原因,请参阅他的“此处解释的内容”链接。此外,无法从 Timer 线程更新 UI!并在其他线程中查看这些其他基于处理程序的答案:(简单)stackoverflow.com/a/6702767/199364,或(显示各种替代方案)stackoverflow.com/a/4598737/199364
    • @quemeful 因为它并不总是关乎方便,而是关乎代码质量和效率。这种方式使用比使用 Handler 更多的资源
    【解决方案4】:

    我希望这个是有帮助的,并且可能会花费更少的精力来实施, Android CountDownTimer class

    例如

     new CountDownTimer(30000, 1000) {
          public void onTick(long millisUntilFinished) {
              mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
          }
    
          public void onFinish() {
              mTextField.setText("done!");
          }  
    }.start();
    

    【讨论】:

      【解决方案5】:

      应该是Timerconcept

      new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval
      
       public void onTick(long millisUntilFinished) {
        }
        public void onFinish() {
       }
      }.start();
      

      方法二::

      给定时器编程

      添加一个名为 time 的新 int 变量。将其设置为 0。 将以下代码添加到 MainActivity.java 中的 onCreate 函数中。

      //Declare the timer
      Timer t = new Timer();
      //Set the schedule function and rate
      t.scheduleAtFixedRate(new TimerTask() {
      
          @Override
          public void run() {
              //Called each time when 1000 milliseconds (1 second) (the period parameter)
          }
      
      },
      //Set how long before to start calling the TimerTask (in milliseconds)
      0,
      //Set the amount of time between each execution (in milliseconds)
      1000);
      

      进入 run 方法并添加以下代码。

      //We must use this function in order to change the text view text
      runOnUiThread(new Runnable() {
      
          @Override
          public void run() {
              TextView tv = (TextView) findViewById(R.id.main_timer_text);
              tv.setText(String.valueOf(time));
              time += 1;
          }
      
      });
      

      【讨论】:

        【解决方案6】:

        这是情境性的。

        Android 文档建议您应该使用AlarmManager 注册一个 Intent,如果您的应用程序可能未运行,该 Intent 将在指定时间触发。

        否则,你应该使用Handler。

        注意:警报管理器旨在 对于您想要拥有的情况 应用程序代码运行在特定 时间,即使你的申请不是 目前正在运行。对于正常时间 操作(滴答声、超时等)它 更容易,更高效 使用处理程序。

        【讨论】:

          【解决方案7】:

          我们开始吧.. 我们需要两节课。我发布的代码每 5 秒(5000 毫秒)更改一次移动音频配置文件...

          我们的第一堂课

          public class ChangeProfileActivityMain extends Activity {
          
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  // TODO Auto-generated method stub
                  super.onCreate(savedInstanceState);
          
                  Timer timer = new Timer();
                  TimerTask updateProfile = new CustomTimerTask(ChangeProfileActivityMain.this);
                  timer.scheduleAtFixedRate(updateProfile, 0, 5000);
              }
          
          }
          

          我们的二等学生

          public class CustomTimerTask extends TimerTask {
          
              private AudioManager audioManager;
              private Context context;
              private Handler mHandler = new Handler();
          
              // Write Custom Constructor to pass Context
              public CustomTimerTask(Context con) {
                  this.context = con;
              }
          
              @Override
              public void run() {
                  // TODO Auto-generated method stub
          
                  // your code starts here.
                  // I have used Thread and Handler as we can not show Toast without starting new thread when we are inside a thread.
                  // As TimePicker has run() thread running., So We must show Toast through Handler.post in a new Thread. Thats how it works in Android..
                  new Thread(new Runnable() {
                      @Override
                      public void run() {
                          audioManager = (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
                          mHandler.post(new Runnable() {
                              @Override
                              public void run() {
                                  if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
                                      audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
                                      Toast.makeText(context, "Ringer Mode set to Normal", Toast.LENGTH_SHORT).show();
                                  } else {
                                      audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                                      Toast.makeText(context, "Ringer Mode set to Silent", Toast.LENGTH_SHORT).show();
                                  }
                              }
                          });
                      }
                  }).start();
          
              }
          
          }
          

          【讨论】:

            【解决方案8】:

            我是 Android 新手,但这是我根据上述答案创建的计时器类。它适用于我的应用程序,但我欢迎任何建议。

            使用示例:

            ...{
            public Handler uiHandler = new Handler();
            
              private Runnable runMethod = new Runnable()
                {
                    public void run()
                    {
                          // do something
                    }
                };
            
                timer = new UITimer(handler, runMethod, timeoutSeconds*1000);       
                    timer.start();
            }...
            
            public class UITimer
            {
                private Handler handler;
                private Runnable runMethod;
                private int intervalMs;
                private boolean enabled = false;
                private boolean oneTime = false;
            
                public UITimer(Handler handler, Runnable runMethod, int intervalMs)
                {
                    this.handler = handler;
                    this.runMethod = runMethod;
                    this.intervalMs = intervalMs;
                }
            
                public UITimer(Handler handler, Runnable runMethod, int intervalMs, boolean oneTime)
                {
                    this(handler, runMethod, intervalMs);
                    this.oneTime = oneTime;
                }
            
                public void start()
                {
                    if (enabled)
                        return;
            
                    if (intervalMs < 1)
                    {
                        Log.e("timer start", "Invalid interval:" + intervalMs);
                        return;
                    }
            
                    enabled = true;
                    handler.postDelayed(timer_tick, intervalMs);        
                }
            
                public void stop()
                {
                    if (!enabled)
                        return;
            
                    enabled = false;
                    handler.removeCallbacks(runMethod);
                    handler.removeCallbacks(timer_tick);
                }
            
                public boolean isEnabled()
                {
                    return enabled;
                }
            
                private Runnable timer_tick = new Runnable()
                {
                    public void run()
                    {
                        if (!enabled)
                            return;
            
                        handler.post(runMethod);
            
                        if (oneTime)
                        {
                            enabled = false;
                            return;
                        }
            
                        handler.postDelayed(timer_tick, intervalMs);
                    }
                }; 
            }
            

            【讨论】:

              【解决方案9】:

              我正在使用一个处理程序并且可以运行来创建一个计时器。我将它包装在一个抽象类中。只需派生/实现它就可以了:

               public static abstract class SimpleTimer {
                  abstract void onTimer();
              
                  private Runnable runnableCode = null;
                  private Handler handler = new Handler();
              
                  void startDelayed(final int intervalMS, int delayMS) {
                      runnableCode = new Runnable() {
                          @Override
                          public void run() {
                              handler.postDelayed(runnableCode, intervalMS);
                              onTimer();
                          }
                      };
                      handler.postDelayed(runnableCode, delayMS);
                  }
              
                  void start(final int intervalMS) {
                      startDelayed(intervalMS, 0);
                  }
              
                  void stop() {
                      handler.removeCallbacks(runnableCode);
                  }
              }
              

              请注意,handler.postDelayed 在要执行的代码之前被调用 - 这将使计时器更接近“预期”的时间。但是,如果计时器运行频繁并且任务(onTimer())很长 - 可能会有重叠。如果您想在任务完成后开始计数intervalMS,请将onTimer() 调用移动到上面一行。

              【讨论】:

                【解决方案10】:

                我相信在 android 上执行此操作的方法是您需要运行后台服务。在该后台应用程序中,创建计时器。当计时器“滴答”(设置您想要等待的时间间隔)时,启动您想要开始的活动。

                http://developer.android.com/guide/topics/fundamentals.html

                【讨论】:

                  【解决方案11】:

                  我曾经使用 (Timer, TimerTask) 和 Handler 定期启动(耗时)任务。现在我已经将整个切换到 RxJava。 RxJava 提供了Observable.timer,它更简单,更不容易出错,使用起来很轻松。

                  public class BetterTimerFragment extends Fragment {
                    public static final String TAG = "BetterTimer";
                    private TextView timeView;
                    private Subscription timerSubscription;
                  
                    @Override
                    public View onCreateView(LayoutInflater inflater,
                                             @Nullable ViewGroup container,
                                             @Nullable Bundle savedInstanceState) {
                      return inflater.inflate(R.layout.fragment_timer, container, false);
                    }
                  
                    @Override
                    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
                      super.onViewCreated(view, savedInstanceState);
                      timeView = (TextView) view.findViewById(R.id.timeView);
                    }
                  
                    @Override
                    public void onResume() {
                      super.onResume();
                  
                      // Right after the app is visible to users, delay 2 seconds
                      // then kick off a (heavy) task every 10 seconds.
                      timerSubscription = Observable.timer(2, 10, TimeUnit.SECONDS)
                          .map(new Func1<Long, String>() {
                            @Override
                            public String call(Long unused) {
                              // TODO: Probably do time-consuming work here.
                              // This runs on a different thread than the main thread.
                              return "Time: " + System.currentTimeMillis();
                            }
                          })
                          .observeOn(AndroidSchedulers.mainThread())
                          .subscribe(new Action1<String>() {
                            @Override
                            public void call(String timeText) {
                              // The result will then be propagated back to the main thread.
                              timeView.setText(timeText);
                            }
                          }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {
                              Log.e(TAG, throwable.getMessage(), throwable);
                            }
                          });
                    }
                  
                    @Override
                    public void onPause() {
                      super.onPause();
                  
                      // Don't kick off tasks when the app gets invisible.
                      timerSubscription.unsubscribe();
                    }
                  }
                  

                  【讨论】:

                    【解决方案12】:

                    对于计时操作,您应该使用Handler

                    如果您需要运行后台服务,AlarmManager 是您的最佳选择。

                    【讨论】:

                      【解决方案13】:

                      这个例子启动了 Kotlin 中销毁的计时器单元

                      private lateinit var timerTask: TimerTask
                      
                       timerTask = object : TimerTask() {
                              override fun run() {
                                  Log.d("KTZ", "$minutes:$seconds");
                                  timeRecordingLiveData.postValue("$minutes:$seconds")
                                  seconds += 1;
                                  if (seconds == 60) {
                                      Log.d("KTZ", "$minutes:$seconds");
                                      timeRecordingLiveData.postValue("$minutes:$seconds")
                                      seconds = 0;
                                      minutes += 1;
                                  }
                              }
                      
                          }
                      

                      在onDestroy()中取消timertask

                      timerTask.cancel()
                      

                      【讨论】:

                        猜你喜欢
                        • 2011-06-03
                        • 2012-03-20
                        • 1970-01-01
                        • 2010-10-02
                        • 2021-09-22
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多