以下计时方式都是Android中常见的计时方式,现总结如下:
实现效果图如下:
下面配合具体代码详细介绍上述计时方式:
实现方式:使用timer.schedule实现任务延迟,定时执行,timerTask实现的是Runnable,从timerTask中抛出的任务交给Handler执行即可:
// timer timerTask
private int minute = 1;//这是分钟
private int second = 1;//这是分钟后面的秒数。这里是以30分钟为例的,所以,minute是30,second是0
private TextView timeView1;
private Button btn_stop1;
private Button btn_start1;
private Timer timer;
private TimerTask timerTask;
private void startMethod1() {
//防止多次点击开启计时器
if (timer != null) {
timer.cancel();
timer = null;
}
if (timerTask != null) {
timerTask = null;
}
timerTask = new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
};
timer = new Timer();
timer.schedule(timerTask, 0, 1000);
}
从timer中抛出的消息,在handler中执行,这个handler就是对时间的格式化,输出01:29的格式:
//这是接收回来处理的消息
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (minute == 0) {
if (second == 0) {
timeView1.setText("Time out !");
if (timer != null) {
timer.cancel();
timer = null;
}
if (timerTask != null) {
timerTask = null;
}
} else {
second--;
if (second >= 10) {
timeView1.setText("0" + minute + ":" + second);
} else {
timeView1.setText("0" + minute + ":0" + second);
}
}
} else {
if (second == 0) {
second = 59;
minute--;
if (minute >= 10) {
timeView1.setText(minute + ":" + second);
} else {
timeView1.setText("0" + minute + ":" + second);
}
} else {
second--;
if (second >= 10) {
if (minute >= 10) {
timeView1.setText(minute + ":" + second);
} else {
timeView1.setText("0" + minute + ":" + second);
}
} else {
if (minute >= 10) {
timeView1.setText(minute + ":0" + second);
} else {
timeView1.setText("0" + minute + ":0" + second);
}
}
}
}
}
};
当然,上述方法可以使用String.format()简化成一行,完成时间的格式化输出:
private String formatTime2(long seconds) {
return String.format(" %02d:%02d", seconds / 60, seconds % 60);
}
由于countDownTimer本身是由handler实现的,其计时是有误差的,简单用法如下,如何屏蔽掉计时误差,请参考handler实现精确计时的两种方式 https://blog.csdn.net/cpcpcp123/article/details/88542113:
private void startMethod2() {
countDownTimer.start();
}
/**
* 第一个参数表示总时间,第二个参数表示间隔时间。意思就是每隔一秒会回调一次方法onTick,然后10秒之后会回调onFinish方法
*/
private CountDownTimer countDownTimer = new CountDownTimer(1000 * 100, 1000) {
@Override
public void onTick(long millisUntilFinished) {
//秒转化成 00:00形式一
// timeView2.setText(formatTime1(millisUntilFinished) + "");
//秒转化成 00:00形式二
timeView2.setText(formatTime2(millisUntilFinished / 1000));
Log.e("hehehe ", millisUntilFinished + " ");
}
@Override
public void onFinish() {
}
};
private void startMethod3() {
mCalHandler.post(mTicker);
}
/**
* 精确修正时间
*/
private Handler mCalHandler = new Handler(Looper.getMainLooper());
private final Runnable mTicker = new Runnable() {
public void run() {
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
mCalHandler.postAtTime(mTicker, next);
timeView3.setText(next + "");
}
};
相关内容可参看:https://blog.csdn.net/ithomer/article/details/6903084
/**
* 通过Handler延迟发送消息的形式实现定时任务。
*/
public static final int CHANGE_TIPS_TIMER_INTERVAL = 1000;
private Handler mChangeTipsHandler = new Handler(Looper.getMainLooper());
int i = 1;
private void startMethod4() {
Runnable mChangeTipsRunnable = new Runnable() {
@Override
public void run() {
timeView4.setText(i++ + "handler");
mChangeTipsHandler.postDelayed(this, CHANGE_TIPS_TIMER_INTERVAL);
}
};
mChangeTipsHandler.post(mChangeTipsRunnable);
}
/**
* ScheduledExecutorService
* ScheduledExecutorService是从JDK1.5做为并发工具类被引进的,存在于java.util.concurrent,这是最理想的定时任务实现方式。
* 相比于上面两个方法,它有以下好处:
* 相比于Timer的单线程,它是通过线程池的方式来执行任务的,所以可以支持多个任务并发执行 ,而且弥补了上面所说的Timer的缺陷
* 可以很灵活的去设定第一次执行任务delay时间
* 提供了良好的约定,以便设定执行的时间间隔
*/
private ScheduledExecutorService scheduledExecutor5 = Executors.newSingleThreadScheduledExecutor();
private void startMethod5() {
Runnable runnable5 = new Runnable() {
@Override
public void run() {
timeView5.setText("每隔 " + taskcount5++ + " 秒执行");
}
};
scheduledExecutor5.scheduleAtFixedRate(runnable5, 0, 1000, TimeUnit.MILLISECONDS);
}
private void startMethod6() {
delayStartTask();
}
private void delayStartTask() {
Intent intent = new Intent();
intent.setAction(DELAY_TASK_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getApplication().getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC, System.currentTimeMillis(), pi);
}