首先说下关于handler自身的误差:
如果使用handler.postDealyed(……, 1000)方式来进行每秒的计时,是不准确的,是的,有很大误差,误差的原因在于在你收到消息,到你重新发出handler.postDealyed的时间,并不是瞬间完成的,这里面有很多逻辑处理的时间,即使没有逻辑处理的时间,handler本身也是耗损性能的,所以消息并不可能按照理想的1000延迟来进行发送,这就导致了误差的累积。
代码:
时钟接口:
public interface IDigitalClock {
/**
* 开始计时
*/
void start();
/**
* 停止
*/
void stop();
/**
* 时钟复位
*/
void reset();
/**
* 重启
*/
void restart();
}
正计时时钟:
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import java.text.DecimalFormat;
public class DefaultDigitalClock implements IDigitalClock {
private final static String TAG = "DefaultDigitalClock";
private final static int TICK_EVENT = 0x1001;
private Ticker mTicker;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == TICK_EVENT) {
long seconds = (long) msg.obj;
String HHMMss = formatElapsedTime(seconds);
clock.tick(seconds, HHMMss);
}
return false;
}
});
private long startTime;
private long elapsedSeconds;
private long maxSeconds;
private ClockOnMainThread clock;
public DefaultDigitalClock(ClockOnMainThread clock) {
this(-1, clock);
}
public DefaultDigitalClock(long maxSeconds, ClockOnMainThread clock) {
this.maxSeconds = maxSeconds;
this.clock = clock;
this.elapsedSeconds = -1;
this.startTime = -1;
}
@Override
public void start() {
startTime = System.currentTimeMillis();
mTicker = new Ticker();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
handler.postAtTime(mTicker, next);
}
@Override
public void stop() {
handler.removeMessages(TICK_EVENT);
if (mTicker != null) {
handler.removeCallbacks(mTicker);
}
}
@Override
public void reset() {
elapsedSeconds = -1;
startTime = -1;
handler.sendMessage(newTick(0));
}
@Override
public void restart() {
stop();
reset();
start();
}
/**
* 在每秒的整点执行
* {@link "https://blog.csdn.net/cpcpcp123/article/details/88542113"}
*/
private final class Ticker implements Runnable {
public void run() {
onTimeChanged();
// 在设定秒数后结束
if (maxSeconds > 0 && elapsedSeconds == maxSeconds) {
stop();
return;
}
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
handler.postAtTime(this, next);
}
};
/**
* 计算时间变化
*/
private void onTimeChanged() {
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
Log.e(TAG, "onTimeChanged() must work on main thread!");
return;
}
elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000;
Log.d(TAG, String.valueOf(elapsedSeconds));
String HHMMss = formatElapsedTime(elapsedSeconds);
clock.tick(elapsedSeconds, HHMMss);
}
private Message newTick(long seconds) {
Message msg = new Message();
msg.what = TICK_EVENT;
msg.obj = seconds;
return msg;
}
/**
* @see android.text.format.DateUtils#formatElapsedTime(long)
* @param elapsedSeconds 经过的秒数
*/
private String formatElapsedTime(long elapsedSeconds) {
// Break the elapsed seconds into hours, minutes, and seconds.
long hours = 0;
long minutes = 0;
long seconds = 0;
if (elapsedSeconds >= 3600) {
hours = elapsedSeconds / 3600;
elapsedSeconds -= hours * 3600;
}
if (elapsedSeconds >= 60) {
minutes = elapsedSeconds / 60;
elapsedSeconds -= minutes * 60;
}
seconds = elapsedSeconds;
String hh = new DecimalFormat("00").format(hours);
String mm = new DecimalFormat("00").format(minutes);
String ss = new DecimalFormat("00").format(seconds);
return String.format("%s:%s:%s", hh, mm, ss);
}
public interface ClockOnMainThread {
void tick(long seconds, String time);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。