Android定时器? 如何?

有人可以给出一个每秒更新一个文本字段的简单例子吗?

我想做一个飞球,每秒需要计算/更新球坐标,这就是为什么我需要某种计时器。

我没有从这里得到任何东西。

好吧,因为这还没有清理,但有3个简单的方法来处理这个问题。 下面是一个显示所有3的例子,最下面的例子显示了我认为最好的方法。 还要记得在onPause中清理你的任务,如果需要的话可以保存状态。

import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Handler.Callback; import android.view.View; import android.widget.Button; import android.widget.TextView; public class main extends Activity { TextView text, text2, text3; long starttime = 0; //this posts a message to the main thread from our timertask //and updates the textfield final Handler h = new Handler(new Callback() { @Override public boolean handleMessage(Message msg) { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text.setText(String.format("%d:%02d", minutes, seconds)); return false; } }); //runs without timer be reposting self Handler h2 = new Handler(); Runnable run = new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text3.setText(String.format("%d:%02d", minutes, seconds)); h2.postDelayed(this, 500); } }; //tells handler to send a message class firstTask extends TimerTask { @Override public void run() { h.sendEmptyMessage(0); } }; //tells activity to run on ui thread class secondTask extends TimerTask { @Override public void run() { main.this.runOnUiThread(new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text2.setText(String.format("%d:%02d", minutes, seconds)); } }); } }; Timer timer = new Timer(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (TextView)findViewById(R.id.text); text2 = (TextView)findViewById(R.id.text2); text3 = (TextView)findViewById(R.id.text3); Button b = (Button)findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button)v; if(b.getText().equals("stop")){ timer.cancel(); timer.purge(); h2.removeCallbacks(run); b.setText("start"); }else{ starttime = System.currentTimeMillis(); timer = new Timer(); timer.schedule(new firstTask(), 0,500); timer.schedule(new secondTask(), 0,500); h2.postDelayed(run, 0); b.setText("stop"); } } }); } @Override public void onPause() { super.onPause(); timer.cancel(); timer.purge(); h2.removeCallbacks(run); Button b = (Button)findViewById(R.id.button); b.setText("start"); } } 

要记住的主要事情是UI只能从主UI线程修改,所以使用一个处理程序或activity.runOnUIThread(Runnable r);

这是我认为是首选的方法。

import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import android.widget.TextView; public class TestActivity extends Activity { TextView timerTextView; long startTime = 0; //runs without a timer by reposting this handler at the end of the runnable Handler timerHandler = new Handler(); Runnable timerRunnable = new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; timerTextView.setText(String.format("%d:%02d", minutes, seconds)); timerHandler.postDelayed(this, 500); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); timerTextView = (TextView) findViewById(R.id.timerTextView); Button b = (Button) findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button) v; if (b.getText().equals("stop")) { timerHandler.removeCallbacks(timerRunnable); b.setText("start"); } else { startTime = System.currentTimeMillis(); timerHandler.postDelayed(timerRunnable, 0); b.setText("stop"); } } }); } @Override public void onPause() { super.onPause(); timerHandler.removeCallbacks(timerRunnable); Button b = (Button)findViewById(R.id.button); b.setText("start"); } }
import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import android.widget.TextView; public class TestActivity extends Activity { TextView timerTextView; long startTime = 0; //runs without a timer by reposting this handler at the end of the runnable Handler timerHandler = new Handler(); Runnable timerRunnable = new Runnable() { @Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; timerTextView.setText(String.format("%d:%02d", minutes, seconds)); timerHandler.postDelayed(this, 500); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); timerTextView = (TextView) findViewById(R.id.timerTextView); Button b = (Button) findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button) v; if (b.getText().equals("stop")) { timerHandler.removeCallbacks(timerRunnable); b.setText("start"); } else { startTime = System.currentTimeMillis(); timerHandler.postDelayed(timerRunnable, 0); b.setText("stop"); } } }); } @Override public void onPause() { super.onPause(); timerHandler.removeCallbacks(timerRunnable); Button b = (Button)findViewById(R.id.button); b.setText("start"); } } 

很简单! 您创build新的计时器。

 Timer timer = new Timer(); 

然后你扩展计时器任务

 class UpdateBallTask extends TimerTask { Ball myBall; public void run() { //calculate the new position of myBall } } 

然后用一些更新间隔将新任务添加到定时器

 final int FPS = 40; TimerTask updateBall = new UpdateBallTask(); timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS); 

免责声明:这不是理想的解决scheme。 这是使用Timer类的解决scheme(如OP所述)。 在Android SDK中,build议使用Handler类(在接受的答案中有示例)。

如果您还需要在UI线程(而不是定时器线程)上运行代码,请在博客上查看: http : //steve.odyfamily.com/?p=12

 public class myActivity extends Activity { private Timer myTimer; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); myTimer = new Timer(); myTimer.schedule(new TimerTask() { @Override public void run() { TimerMethod(); } }, 0, 1000); } private void TimerMethod() { //This method is called directly by the timer //and runs in the same thread as the timer. //We call the method that will work with the UI //through the runOnUiThread method. this.runOnUiThread(Timer_Tick); } private Runnable Timer_Tick = new Runnable() { public void run() { //This method runs in the same thread as the UI. //Do something to the UI thread here } }; } 

如果只是想在将来的时间间隔内安排倒数计时,则可以使用自API级别1以来可用的CountDownTimer类。

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

这是一个简单的计时器代码:

 final int sekundi = 0 ; Timer timer = new Timer(); TimerTask t = new TimerTask() { int sec = 0; @Override public void run() { System.out.println("1"); } }; timer.scheduleAtFixedRate(t,1000,1000); 

我觉得你可以用Rx的方式来做到这一点:

  timerSubscribe = Observable.interval(1, TimeUnit.SECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { //TODO do your stuff } }); 

并取消这样的:

 timerSubscribe.unsubscribe(); 

Rx定时器http://reactivex.io/documentation/operators/timer.html

您希望您的UI更新发生在已经存在的UI线程中。

最好的方法是使用一个使用postDelayed的处理程序在延迟之后运行一个Runnable(每个运行计划下一个); 用removeCallbacks清除callback。

你已经find了正确的地方,所以再看一遍,也许澄清为什么代码示例不是你想要的。 (另请参阅从计时器更新UI中的相同文章)。

他是简单的解决scheme,在我的应用程序工作正常。

  public class MyActivity extends Acitivity { TextView myTextView; boolean someCondition=true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); myTextView = (TextView) findViewById(R.id.refreshing_field); //starting our task which update textview every 1000 ms new RefreshTask().execute(); } //class which updates our textview every second class RefreshTask extends AsyncTask { @Override protected void onProgressUpdate(Object... values) { super.onProgressUpdate(values); String text = String.valueOf(System.currentTimeMillis()); myTextView.setText(text); } @Override protected Object doInBackground(Object... params) { while(someCondition) { try { //sleep for 1s in background... Thread.sleep(1000); //and update textview in ui thread publishProgress(); } catch (InterruptedException e) { e.printStackTrace(); }; return null; } } } 

因为这个问题仍然吸引了很多谷歌search的用户(关于Android定时器),我想插入我的两个硬币。

首先, Timer类将在Java 9中被弃用(阅读接受的答案) 。

官方build议的方法是使用ScheduledThreadPoolExecutor ,这是更有效和function丰富,可以额外安排命令在给定的延迟后运行,或定期执行。 另外,它还提供了ThreadPoolExecutor的更多灵活性和function。

这是一个使用普通function的例子。

  1. 创build执行者服务:

     final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1); 
  2. 只是安排你可以运行:

     final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit); 
  3. 您现在可以使用future来取消任务或检查是否完成,例如:

     future.isDone(); 

希望你会发现这有助于在Android中创build任务。

完整的例子:

 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS); if (sampleFutureTimer.isDone()){ // Do something which will save world. } 

您需要创build一个线程来处理更新循环,并使用它来更新textarea。 棘手的部分是只有主线程才能真正修改ui,所以更新循环线程需要通知主线程进行更新。 这是使用处理程序完成的。

看看这个链接: http : //developer.android.com/guide/topics/ui/dialogs.html#点击标题为“示例ProgressDialog与第二个线程”的部分。 这是您需要做的一个例子,除了进度对话框而不是文本框。

 void method(boolean u,int max) { uu=u; maxi=max; if (uu==true) { CountDownTimer uy = new CountDownTimer(maxi, 1000) { public void onFinish() { text.setText("Finish"); } @Override public void onTick(long l) { String currentTimeString=DateFormat.getTimeInstance().format(new Date()); text.setText(currentTimeString); } }.start(); } else{text.setText("Stop "); } 

如果任何人有兴趣,我开始玩创build一个标准的对象运行在一个活动的UI线程。 似乎工作正常。 评论欢迎。 我很喜欢这个在布局devise器上作为一个组件拖动到一个活动。 不能相信像这样的东西不存在。

 package com.example.util.timer; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; public class ActivityTimer { private Activity m_Activity; private boolean m_Enabled; private Timer m_Timer; private long m_Delay; private long m_Period; private ActivityTimerListener m_Listener; private ActivityTimer _self; private boolean m_FireOnce; public ActivityTimer() { m_Delay = 0; m_Period = 100; m_Listener = null; m_FireOnce = false; _self = this; } public boolean isEnabled() { return m_Enabled; } public void setEnabled(boolean enabled) { if (m_Enabled == enabled) return; // Disable any existing timer before we enable a new one Disable(); if (enabled) { Enable(); } } private void Enable() { if (m_Enabled) return; m_Enabled = true; m_Timer = new Timer(); if (m_FireOnce) { m_Timer.schedule(new TimerTask() { @Override public void run() { OnTick(); } }, m_Delay); } else { m_Timer.schedule(new TimerTask() { @Override public void run() { OnTick(); } }, m_Delay, m_Period); } } private void Disable() { if (!m_Enabled) return; m_Enabled = false; if (m_Timer == null) return; m_Timer.cancel(); m_Timer.purge(); m_Timer = null; } private void OnTick() { if (m_Activity != null && m_Listener != null) { m_Activity.runOnUiThread(new Runnable() { @Override public void run() { m_Listener.OnTimerTick(m_Activity, _self); } }); } if (m_FireOnce) Disable(); } public long getDelay() { return m_Delay; } public void setDelay(long delay) { m_Delay = delay; } public long getPeriod() { return m_Period; } public void setPeriod(long period) { if (m_Period == period) return; m_Period = period; } public Activity getActivity() { return m_Activity; } public void setActivity(Activity activity) { if (m_Activity == activity) return; m_Activity = activity; } public ActivityTimerListener getActionListener() { return m_Listener; } public void setActionListener(ActivityTimerListener listener) { m_Listener = listener; } public void start() { if (m_Enabled) return; Enable(); } public boolean isFireOnlyOnce() { return m_FireOnce; } public void setFireOnlyOnce(boolean fireOnce) { m_FireOnce = fireOnce; } } 

在活动中,我有这onStart:

 @Override protected void onStart() { super.onStart(); m_Timer = new ActivityTimer(); m_Timer.setFireOnlyOnce(true); m_Timer.setActivity(this); m_Timer.setActionListener(this); m_Timer.setDelay(3000); m_Timer.start(); } 

这是一个简单可靠的方法…

把下面的代码放到你的Activity中,当你的活动处于“恢复”状态时,将在UI线程中每秒调用一次tick()方法。 当然,你可以改变tick()方法来做你想做的事情,或者或多或less地调用它。

 @Override public void onPause() { _handler = null; super.onPause(); } private Handler _handler; @Override public void onResume() { super.onResume(); _handler = new Handler(); Runnable r = new Runnable() { public void run() { if (_handler == _h0) { tick(); _handler.postDelayed(this, 1000); } } private final Handler _h0 = _handler; }; r.run(); } private void tick() { System.out.println("Tick " + System.currentTimeMillis()); } 

对于那些有兴趣的人来说,如果你的活动在tick时间内暂停和恢复,那么“_h0 = _handler”代码是必要的,以避免两个定时器同时运行。

 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import android.app.Activity; public class MainActivity extends Activity { CheckBox optSingleShot; Button btnStart, btnCancel; TextView textCounter; Timer timer; MyTimerTask myTimerTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); optSingleShot = (CheckBox)findViewById(R.id.singleshot); btnStart = (Button)findViewById(R.id.start); btnCancel = (Button)findViewById(R.id.cancel); textCounter = (TextView)findViewById(R.id.counter); btnStart.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { if(timer != null){ timer.cancel(); } //re-schedule timer here //otherwise, IllegalStateException of //"TimerTask is scheduled already" //will be thrown timer = new Timer(); myTimerTask = new MyTimerTask(); if(optSingleShot.isChecked()){ //singleshot delay 1000 ms timer.schedule(myTimerTask, 1000); }else{ //delay 1000ms, repeat in 5000ms timer.schedule(myTimerTask, 1000, 5000); } }}); btnCancel.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if (timer!=null){ timer.cancel(); timer = null; } } }); } class MyTimerTask extends TimerTask { @Override public void run() { Calendar calendar = Calendar.getInstance(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a"); final String strDate = simpleDateFormat.format(calendar.getTime()); runOnUiThread(new Runnable(){ @Override public void run() { textCounter.setText(strDate); }}); } } } 

.XML

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:autoLink="web" android:text="http://android-er.blogspot.com/" android:textStyle="bold" /> <CheckBox android:id="@+id/singleshot" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Single Shot"/> 

你也可以使用一个animation师:

 int secondsToRun = 999; ValueAnimator timer = ValueAnimator.ofInt(secondsToRun); timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator()); timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int elapsedSeconds = (int) animation.getAnimatedValue(); int minutes = elapsedSeconds / 60; int seconds = elapsedSeconds % 60; textView.setText(String.format("%d:%02d", minutes, seconds)); } }); timer.start(); 

对于那些不能依靠计时器的人 ,我提出了一个实用课,其中一个build议是:

 public class TimerTextHelper implements Runnable { private final Handler handler = new Handler(); private final TextView textView; private volatile long startTime; private volatile long elapsedTime; public TimerTextHelper(TextView textView) { this.textView = textView; } @Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; textView.setText(String.format("%d:%02d", minutes, seconds)); if (elapsedTime == -1) { handler.postDelayed(this, 500); } } public void start() { this.startTime = System.currentTimeMillis(); this.elapsedTime = -1; handler.post(this); } public void stop() { this.elapsedTime = System.currentTimeMillis() - startTime; handler.removeCallbacks(this); } public long getElapsedTime() { return elapsedTime; } 

}

使用..只是做:

  TimerTextHelper timerTextHelper = new TimerTextHelper(textView); timerTextHelper.start(); 

…..

  timerTextHelper.stop(); long elapsedTime = timerTextHelper.getElapsedTime(); 

如果你已经有delta时间了。

 public class Timer { private float lastFrameChanged; private float frameDuration; private Runnable r; public Timer(float frameDuration, Runnable r) { this.frameDuration = frameDuration; this.lastFrameChanged = 0; this.r = r; } public void update(float dt) { lastFrameChanged += dt; if (lastFrameChanged > frameDuration) { lastFrameChanged = 0; r.run(); } } }