1, 概述
Chronometer在平时开发时使用广泛,使用简单, 只需要调用三个简单的方法就可以。
2, Chronometer
Chronometer是TextView的子类,这个组只能以1秒的时间间隔进行计时,并显示出计时结果。使用Handler来实现。
2.1 开发方法
Chronometer开发很简单,
private Chronometer timer;
timer = (Chronometer)findViewById(R.id.timer); // 定义并获取组件
timer.setBase(SystemClock.elapsedRealtime()); // 设置起始时间
timer.start(); // 开始每隔1s开始计时
timer.stop(); // 停止计时
2.2 原理分析
1, setBase
setBase方法如下,
public void setBase(long base) {
mBase = base; // 设置时间基准
dispatchChronometerTick(); // 回调
updateText(SystemClock.elapsedRealtime()); // 跟新显示
}
setBase方法主要是设置mBase变量,该变量是时间基准。
2, start方法
public void start() {
mStarted = true;
updateRunning();
}
mStarted变量是记录计时是否开始。
updateRunning方法如下,
private void updateRunning() {
boolean running = mVisible && mStarted; // 如果未开始计时,并且该控件可见
if (running != mRunning) {
if (running) {
updateText(SystemClock.elapsedRealtime()); // 获取当前时间然后更新
dispatchChronometerTick(); // 回调
mHandler.sendMessageDelayed(Message.obtain(mHandler, TICK_WHAT), 1000);
} else {
mHandler.removeMessages(TICK_WHAT);// 移除消息。
}
mRunning = running;
}
}
mVisible变量表示该控件是否可见, mRunning变量表示是否在计时。
利用handler进行计时,相当于一个死循环,每隔1s钟执行一次更新和回调。一直到调用stop方法为止。
private Handler mHandler = new Handler() {
public void handleMessage(Message m) {
if (mRunning) {
updateText(SystemClock.elapsedRealtime());
dispatchChronometerTick();
sendMessageDelayed(Message.obtain(this, TICK_WHAT), 1000);
}
}
};
3,stop
public void stop() {
mStarted = false;
updateRunning();
}
将mStarted赋值为空,然后在updateRunning方法中移除消息,这样就终止了计时。
mHandler.removeMessages(TICK_WHAT);// 移除消息。
4, updateText
private synchronized void updateText(long now) {
mNow = now;
long seconds = now - mBase;
seconds /= 1000;
String text = DateUtils.formatElapsedTime(mRecycle, seconds);
if (mFormat != null) {
Locale loc = Locale.getDefault();
if (mFormatter == null || !loc.equals(mFormatterLocale)) {
mFormatterLocale = loc;
mFormatter = new Formatter(mFormatBuilder, loc);
}
mFormatBuilder.setLength(0);
mFormatterArgs[0] = text;
try {
mFormatter.format(mFormat, mFormatterArgs);
text = mFormatBuilder.toString();
} catch (IllegalFormatException ex) {
if (!mLogged) {
Log.w(TAG, "Illegal format string: " + mFormat);
mLogged = true;
}
}
}
setText(text);
}
首先将当前时间减去基准时间(ms),然后转化为s,转化为特定的时间格式,最后调用setText方法显示到界面。
5, dispatchChronometerTick
void dispatchChronometerTick() {
if (mOnChronometerTickListener != null) {
mOnChronometerTickListener.onChronometerTick(this);
}
}
mOnChronometerTickListener是OnChronometerTickListener对象,而OnChronometerTickListener是Chronometer的内部接口,
public interface OnChronometerTickListener {
void onChronometerTick(Chronometer chronometer);
}
mOnChronometerTickListener变量是通过setOnChronometerTickListener进行赋值的。
public void setOnChronometerTickListener(OnChronometerTickListener listener) {
mOnChronometerTickListener = listener;
}
由此看来,这是一个标准的接口回调方法。
如果需要回调,只需要继承OnChronometerTickListener接口,然后调用setOnChronometerTickListener方法,最后实现onChronometerTick方法就可以了。
onChronometerTick方法会在调用start时回调一次,然后每个1s回调一次,一直到调用stop方法为止。
小结:
1,Chronometer使用简单,但是只能间隔1s进行计时。
2,有标准的回调方法,并且回调方法也是间隔1s执行一次。
3,使用handler实现,其实开发时也可以利用handler简单的写一个类,这样可以控制间隔时间。