代码之家  ›  专栏  ›  技术社区  ›  n179911

如何在Android中设置计时器

  •  161
  • n179911  · 技术社区  · 15 年前

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

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

    12 回复  |  直到 7 年前
        1
  •  138
  •   Silvio Mayolo    8 年前

    标准的Java方式使用计时器 java.util.Timer java.util.TimerTask 在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) .

        2
  •  147
  •   Farkie    8 年前

    是的,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);
    

    或A 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

        3
  •  128
  •   n611x007 David Dossot    11 年前

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

    对于重复任务:

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

    对于单个任务运行:

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


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

        4
  •  18
  •   Arunjith R S    7 年前

    希望这一点有所帮助,可以少花点力气来落实, 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
  •  16
  •   vkulkarni    11 年前

    可能 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();
    

    方法2:

    编程定时器

    添加一个名为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
  •  11
  •   Timothy Lee Russell    15 年前

    它是情境的。

    Android文档建议您使用 AlarmManager 注册在应用程序可能不运行时在指定时间激发的意图。

    否则,您应该使用处理程序。

    注意:报警管理器是用于 如果你想要 应用程序代码在特定的 时间,即使你的申请没有 当前正在运行。对于正常定时 操作(计时、超时等)IT 更容易更有效地 使用汉德勒。

        7
  •  11
  •   Rizwan Sohaib    13 年前

    我们走了…我们需要两节课。我正在发布一个代码,每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
  •  5
  •   user868020    14 年前

    我是一个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
  •  3
  •   elcuco    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
  •  2
  •   Crowe T. Robot    15 年前

    我相信在Android上这样做的方法是你需要一个后台服务来运行。在后台应用程序中,创建计时器。当计时器“滴答”时(设置等待时间间隔),启动要启动的活动。

    http://developer.android.com/guide/topics/fundamentals.html (<--本文解释了Android开发的活动、服务、意图和其他核心基础之间的关系)

        11
  •  1
  •   Thuy Trinh    10 年前

    我过去经常使用( 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
  •  1
  •   Rahul Sharma Rashid Kurbanov    7 年前

    对于定时操作,应使用 Handler .

    如果您需要运行后台服务,那么AlarmManager就是您的选择。