Skip to content

Commit e66470d

Browse files
committed
修复有毫秒时的倒计时不正确问题
1 parent 6094530 commit e66470d

File tree

2 files changed

+92
-98
lines changed

2 files changed

+92
-98
lines changed

library/src/main/java/cn/iwgang/countdownview/CountdownView.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -977,11 +977,10 @@ public void start(long millisecond) {
977977
countDownInterval = 1000;
978978
}
979979

980-
mCustomCountDownTimer = new CustomCountDownTimer(millisecond, countDownInterval);
981-
mCustomCountDownTimer.setCustomCountDownTimerListener(new CustomCountDownTimer.CustomCountDownTimerListener() {
980+
mCustomCountDownTimer = new CustomCountDownTimer(millisecond, countDownInterval) {
982981
@Override
983-
public void onTick(long remainMillis) {
984-
updateShow(remainMillis);
982+
public void onTick(long millisUntilFinished) {
983+
updateShow(millisUntilFinished);
985984
}
986985

987986
@Override
@@ -993,12 +992,7 @@ public void onFinish() {
993992
mOnCountdownEndListener.onEnd(CountdownView.this);
994993
}
995994
}
996-
997-
@Override
998-
public void onCancel() {
999-
1000-
}
1001-
});
995+
};
1002996
mCustomCountDownTimer.start();
1003997
}
1004998

library/src/main/java/cn/iwgang/countdownview/CustomCountDownTimer.java

Lines changed: 88 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,122 +2,122 @@
22

33
import android.os.Handler;
44
import android.os.Message;
5-
6-
import java.lang.ref.WeakReference;
7-
import java.util.Timer;
8-
import java.util.TimerTask;
5+
import android.os.SystemClock;
96

107
/**
8+
* 使用android.os.CountDownTimer的源码
9+
* 1. 对回调onTick做了细小调整,已解决最后1秒不会倒计时到0,要等待2秒才回调onFinish
10+
* 2. 添加了一些自定义方法
1111
* Created by iWgang on 15/10/18.
1212
* https://github.com/iwgang/CountdownView
1313
*/
14-
public class CustomCountDownTimer {
15-
private static final int HANDLER_WHAT_TICK = 10001;
16-
private static final int HANDLER_WHAT_END = 10002;
17-
private static final int HANDLER_WHAT_CANCEL = 10003;
18-
19-
private long mMillisInFuture;
20-
private long mCountDownInterval;
21-
private boolean isCancel;
22-
private boolean isPause = true;
23-
private Timer mTimer;
24-
private CustomCountDownTimerListener mCustomCountDownTimerListener;
25-
private MyHandler mHandler;
26-
14+
public abstract class CustomCountDownTimer {
15+
private static final int MSG = 1;
16+
private final long mMillisInFuture;
17+
private final long mCountdownInterval;
18+
private long mStopTimeInFuture;
19+
private long mPauseTimeInFuture;
20+
private boolean isStop = false;
21+
private boolean isPause = false;
22+
23+
/**
24+
* @param millisInFuture 总倒计时时间
25+
* @param countDownInterval 倒计时间隔时间
26+
*/
2727
public CustomCountDownTimer(long millisInFuture, long countDownInterval) {
28-
this.mMillisInFuture = millisInFuture;
29-
this.mCountDownInterval = countDownInterval;
30-
mHandler = new MyHandler(this);
28+
// 解决秒数有时会一开始就减去了2秒问题(如10秒总数的,刚开始就8999,然后没有不会显示9秒,直接到8秒)
29+
if (countDownInterval > 1000) millisInFuture += 15;
30+
mMillisInFuture = millisInFuture;
31+
mCountdownInterval = countDownInterval;
3132
}
3233

33-
public void stop() {
34-
if (isCancel) return ;
35-
36-
isCancel = true;
37-
mHandler.sendEmptyMessage(HANDLER_WHAT_CANCEL);
38-
if (null != mTimer) {
39-
mTimer.cancel();
40-
mTimer = null;
34+
private synchronized CustomCountDownTimer start(long millisInFuture) {
35+
isStop = false;
36+
if (millisInFuture <= 0) {
37+
onFinish();
38+
return this;
4139
}
40+
mStopTimeInFuture = SystemClock.elapsedRealtime() + millisInFuture;
41+
mHandler.sendMessage(mHandler.obtainMessage(MSG));
42+
return this;
4243
}
4344

44-
public void start() {
45-
if (isPause) {
46-
isPause = false;
47-
mTimer = new Timer();
48-
mTimer.schedule(new TimerTask() {
49-
@Override
50-
public void run() {
51-
if (isCancel) return ;
52-
53-
mMillisInFuture -= mCountDownInterval;
54-
mHandler.sendEmptyMessage(HANDLER_WHAT_TICK);
55-
56-
if (mMillisInFuture <= 0) {
57-
mMillisInFuture = 0;
58-
isCancel = true;
59-
mHandler.sendEmptyMessage(HANDLER_WHAT_END);
60-
mTimer.cancel();
61-
}
62-
}
63-
}, 0, mCountDownInterval);
64-
}
45+
/**
46+
* 开始倒计时
47+
*/
48+
public synchronized final void start() {
49+
start(mMillisInFuture);
6550
}
6651

67-
public void pause() {
68-
isPause = true;
69-
if (null != mTimer) {
70-
mTimer.cancel();
71-
mTimer = null;
72-
}
52+
/**
53+
* 停止倒计时
54+
*/
55+
public synchronized final void stop() {
56+
isStop = true;
57+
mHandler.removeMessages(MSG);
7358
}
7459

75-
public void restart() {
76-
start();
77-
}
60+
/**
61+
* 暂时倒计时
62+
* 调用{@link #restart()}方法重新开始
63+
*/
64+
public synchronized final void pause() {
65+
if (isStop) return ;
7866

79-
public void setCustomCountDownTimerListener(CustomCountDownTimerListener customCountDownTimerListener) {
80-
this.mCustomCountDownTimerListener = customCountDownTimerListener;
67+
isPause = true;
68+
mPauseTimeInFuture = mStopTimeInFuture - SystemClock.elapsedRealtime();
69+
mHandler.removeMessages(MSG);
8170
}
8271

83-
public interface CustomCountDownTimerListener {
84-
void onTick(long remainMillis);
85-
void onFinish();
86-
void onCancel();
72+
/**
73+
* 重新开始
74+
*/
75+
public synchronized final void restart() {
76+
if (isStop || !isPause) return ;
77+
78+
isPause = false;
79+
start(mPauseTimeInFuture);
8780
}
8881

89-
private static class MyHandler extends Handler {
90-
WeakReference<CustomCountDownTimer> wrf = null;
82+
/**
83+
* 倒计时间隔回调
84+
* @param millisUntilFinished 剩余毫秒数
85+
*/
86+
public abstract void onTick(long millisUntilFinished);
9187

92-
public MyHandler(CustomCountDownTimer customCountDownTimer) {
93-
wrf = new WeakReference<>(customCountDownTimer);
94-
}
88+
/**
89+
* 倒计时结束回调
90+
*/
91+
public abstract void onFinish();
92+
93+
94+
private Handler mHandler = new Handler() {
9595

9696
@Override
9797
public void handleMessage(Message msg) {
98-
super.handleMessage(msg);
9998

100-
if (null == wrf) {
101-
return ;
102-
}
99+
synchronized (CustomCountDownTimer.this) {
100+
if (isStop || isPause) {
101+
return;
102+
}
103103

104-
CustomCountDownTimer curCustomCountDownTimer = wrf.get();
104+
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
105+
if (millisLeft <= 0) {
106+
onFinish();
107+
} else {
108+
long lastTickStart = SystemClock.elapsedRealtime();
109+
onTick(millisLeft);
105110

106-
if (null == curCustomCountDownTimer || null == curCustomCountDownTimer.mCustomCountDownTimerListener) return ;
111+
// take into account user's onTick taking time to execute
112+
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
107113

108-
switch (msg.what) {
109-
case HANDLER_WHAT_TICK:
110-
curCustomCountDownTimer.mCustomCountDownTimerListener.onTick(curCustomCountDownTimer.mMillisInFuture);
111-
break;
112-
case HANDLER_WHAT_END:
113-
curCustomCountDownTimer.mCustomCountDownTimerListener.onFinish();
114-
break;
115-
case HANDLER_WHAT_CANCEL:
116-
curCustomCountDownTimer.mCustomCountDownTimerListener.onCancel();
117-
break;
114+
// special case: user's onTick took more than interval to
115+
// complete, skip to next interval
116+
while (delay < 0) delay += mCountdownInterval;
117+
118+
sendMessageDelayed(obtainMessage(MSG), delay);
119+
}
118120
}
119121
}
120-
121-
}
122-
122+
};
123123
}

0 commit comments

Comments
 (0)