好的,既然这个问题还没有解决,那么有三种简单的方法来处理它。下面是一个展示所有三种方法的示例,底部还有一个示例,展示了我认为更可取的方法。同时,请记得在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;
//定义Handler对象h并设置回调函数Callback,该回调函数会在主线程中更新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;
}
});
//定义Handler对象h2以及Runnable对象run,该runnable对象会在主线程中更新textfield3控件
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);
}
};
//定义TimerTask子类firstTask,用于告诉handler发送一个空消息
class firstTask extends TimerTask {
@Override
public void run() {
h.sendEmptyMessage(0);
}
};
//定义TimerTask子类secondTask,用于在主线程中更新textfield2控件
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);
//获取三个textfield控件以及一个button控件
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");
}
}
});
}
//当Activity进入后台时,停止计时器
@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线程修改,所以使用Handler或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;
//通过在可运行的结束处重新发布此处理程序而无需计时器
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("开始");
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Button b = (Button) v;
if (b.getText().equals("停止")) {
timerHandler.removeCallbacks(timerRunnable);
b.setText("开始");
} else {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
b.setText("停止");
}
}
});
}
//当活动不再处于前台时调用
@Override
public void onPause() {
super.onPause();
timerHandler.removeCallbacks(timerRunnable);
Button b = (Button)findViewById(R.id.button);
b.setText("开始");
}
}
很简单!你可以创建一个新的计时器。
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);
免责声明:这不是理想的解决方案。这是使用Timer类的解决方案(正如OP所请求的)。在Android SDK中,建议使用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) {
editText.setText("Seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
editText.setText("Done");
}
}.start();
SS:MiMi
?谢谢。 - Ruchir Baronia这是一个简单的计时器代码:
Timer timer = new Timer();
TimerTask t = new TimerTask() {
@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
implementation "io.reactivex.rxjava2:rxjava:2.x.y"
由于我们只有一个简单的、非重复的任务,我们可以使用Completable
对象:
(将x
和y
替换为current version number)
Completable.timer(2, TimeUnit.SECONDS, Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> {
// Timer finished, do something...
});
对于重复任务,您可以以类似的方式使用Observable
:
Observable.interval(2, TimeUnit.SECONDS, Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(tick -> {
// called every 2 seconds, do something...
}, throwable -> {
// handle error
});
Schedulers.computation()
确保我们的计时器在后台线程上运行,.observeOn(AndroidSchedulers.mainThread())
表示计时器完成后我们要运行的代码将在主线程上执行。
为避免不必要的内存泄漏,在 Activity/Fragment 销毁时应确保取消订阅。
.subscribe()
方法返回的 Subscription
保存在变量中,然后在想要停止计时器时调用 subscription.unsubscribe()
即可。 - MicerCreate executor service:
final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
Just schedule you runnable:
final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit);
You can now use future
to cancel the task or check if it is done for example:
future.isDone();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS);
if (sampleFutureTimer.isDone()){
// Do something which will save world.
}
对于想要使用 Kotlin 实现此操作的人:
val timer = fixedRateTimer(period = 1000L) {
val currentTime: Date = Calendar.getInstance().time
runOnUiThread {
tvFOO.text = currentTime.toString()
}
}
timer.cancel()
这个函数还有许多其他选项,试试看吧。
import kotlin.concurrent.fixedRateTimer
val timer = fixedRateTimer("Tag", false, 1000, 2500) { /* Your code here */ }
使用 Kotlin 很简单