对于一个Java开发者来说,想到定时器(计时器,倒计时)的应用 一般都会想到使用 java.util.Timer 和 java.util.TimerTask , 在Android中使用这2个类也可以实现计时的功能 但是使用起来还是有点麻烦的, 特别是在UI界面需要更新的时候, 例如 实现一个倒计时的界面, 在一个TextView中显示当前剩余的时间, 如果在TimerTask中计时,则无法更新TextView显示的剩余时间(在非UI线程中 不能访问UI组件),可以通过runOnUiThread函数来实现 但是多少有点烦琐.
在Android 实现定时比较推荐的方式还是使用 android.os.Handler 中的 postXXX 和sendXXX 等方法. 细心的开发者可能已经注意到Android提供了一个倒计时的助手类 android.os.CountDownTimer 来方便实现倒计时的功能. 她就是通过handler的 sendMessageDelayed 来实现的. 使用该类来显示一个倒计时的TextView是很方便的:
01.
TextView mTv;
02.
@Override
03.
protected
void
onCreate(Bundle savedInstanceState) {
04.
super
.onCreate(savedInstanceState);
05.
setContentView(R.layout.main);
06.
mTv = (TextView) findViewById(R.id.tv);
07.
mTv.setText(
"test"
);
08.
new
CountDownTimer(
30000
,
100
) {
09.
10.
@Override
11.
public
void
onTick(
long
millisUntilFinished) {
12.
mTv.setText(
"seconds remaining: "
+
13.
millisUntilFinished /
1000
+
" S "
+(millisUntilFinished %
1000
)/
100
);
14.
}
15.
16.
@Override
17.
public
void
onFinish() {
18.
mTv.setText(
"Done!"
);
19.
}
20.
}.start();
21.
}
CountDownTimer的源代码如下:
01.
public
abstract
class
CountDownTimer {
02.
03.
/**
04.
* Millis since epoch when alarm should stop.
05.
*/
06.
private
final
long
mMillisInFuture;
07.
08.
/**
09.
* The interval in millis that the user receives callbacks
10.
*/
11.
private
final
long
mCountdownInterval;
12.
13.
private
long
mStopTimeInFuture;
14.
15.
/**
16.
* @param millisInFuture The number of millis in the future from the call
17.
* to {@link #start()} until the countdown is done and {@link #onFinish()}
18.
* is called.
19.
* @param countDownInterval The interval along the way to receive
20.
* {@link #onTick(long)} callbacks.
21.
*/
22.
public
CountDownTimer(
long
millisInFuture,
long
countDownInterval) {
23.
mMillisInFuture = millisInFuture;
24.
mCountdownInterval = countDownInterval;
25.
}
26.
27.
/**
28.
* Cancel the countdown.
29.
*/
30.
public
final
void
cancel() {
31.
mHandler.removeMessages(MSG);
32.
}
33.
34.
/**
35.
* Start the countdown.
36.
*/
37.
public
synchronized
final
CountDownTimer start() {
38.
if
(mMillisInFuture <=
0
) {
39.
onFinish();
40.
return
this
;
41.
}
42.
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
43.
mHandler.sendMessage(mHandler.obtainMessage(MSG));
44.
return
this
;
45.
}
46.
47.
48.
/**
49.
* Callback fired on regular interval.
50.
* @param millisUntilFinished The amount of time until finished.
51.
*/
52.
public
abstract
void
onTick(
long
millisUntilFinished);
53.
54.
/**
55.
* Callback fired when the time is up.
56.
*/
57.
public
abstract
void
onFinish();
58.
59.
60.
private
static
final
int
MSG =
1
;
61.
62.
63.
// handles counting down
64.
private
Handler mHandler =
new
Handler() {
65.
66.
@Override
67.
public
void
handleMessage(Message msg) {
68.
69.
synchronized
(CountDownTimer.
this
) {
70.
final
long
millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
71.
72.
if
(millisLeft <=
0
) {
73.
onFinish();
74.
}
else
if
(millisLeft < mCountdownInterval) {
75.
// no tick, just delay until done
76.
sendMessageDelayed(obtainMessage(MSG), millisLeft);
77.
}
else
{
78.
long
lastTickStart = SystemClock.elapsedRealtime();
79.
onTick(millisLeft);
80.
81.
// take into account user's onTick taking time to execute
82.
long
delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
83.
84.
// special case: user's onTick took more than interval to
85.
// complete, skip to next interval
86.
while
(delay <
0
) delay += mCountdownInterval;
87.
88.
sendMessageDelayed(obtainMessage(MSG), delay);
89.
}
90.
}
91.
}
92.
};