Android CountDownTimer重写
Android 倒计时器重写,实现可重复使用,动态修改计时时间
CountDownTimerRew 是一个可重写、动态修改计时时间的 Android 倒计时器类。它允许开发者设置倒计时总时长、间隔时间,并通过 onTick 和 onFinish 方法实现定时回调。该类支持动态修改计时参数,如 millisInFuture 和 countDownInterval,并提供了 cancel 和 start 方法控制计时器的启停。通过 WeakHandler 类,CountDownTimerRew 避免了内存泄漏问题。使用时,开发者只需继承该类并实现 onTick 和 onFinish 方法即可。
CountDownTimerRew 类
public abstract class CountDownTimerRew {/*** Millis since epoch when alarm should stop.*/private long mMillisInFuture;/*** The interval in millis that the user receives callbacks*/private long mCountdownInterval;private long mStopTimeInFuture;/*** boolean representing if the timer was cancelled*/private boolean mCancelled = false;private Object mTag;/*** @param millisInFuture The number of millis in the future from the call* to {@link #start()} until the countdown is done and {@link #onFinish()}* is called.* @param countDownInterval The interval along the way to receive* {@link #onTick(long, Object)} callbacks.*/public CountDownTimerRew(long millisInFuture, long countDownInterval) {mMillisInFuture = millisInFuture;mCountdownInterval = countDownInterval;}public CountDownTimerRew setTag(Object mTag) {this.mTag = mTag;return this;}public CountDownTimerRew setMillisInFuture(long mMillisInFuture) {this.mMillisInFuture = mMillisInFuture;return this;}public CountDownTimerRew setCountdownInterval(long mCountdownInterval) {this.mCountdownInterval = mCountdownInterval;return this;}/*** Cancel the countdown.*/public synchronized final void cancel() {mCancelled = true;mHandler.removeMessages(MSG);}/*** Start the countdown.*/public synchronized final CountDownTimerRew start() {mCancelled = false;if (mMillisInFuture <= 0) {onFinish();return this;}mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;mHandler.sendMessage(mHandler.obtainMessage(MSG));return this;}/*** Callback fired on regular interval.** @param millisUntilFinished The amount of time until finished.*/public abstract void onTick(long millisUntilFinished, Object mTag);/*** Callback fired when the time is up.*/public abstract void onFinish();private static final int MSG = 1;// handles counting downprivate final Handler mHandler = new WeakHandler(Looper.getMainLooper()) {@Overridepublic void handleMessage(@NonNull Message msg) {synchronized (CountDownTimerRew.this) {if (mCancelled) {return;}final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();if (millisLeft <= 0) {onFinish();} else {long lastTickStart = SystemClock.elapsedRealtime();onTick(millisLeft, mTag);// take into account user's onTick taking time to executelong lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;long delay;if (millisLeft < mCountdownInterval) {// just delay until donedelay = millisLeft - lastTickDuration;// special case: user's onTick took more than interval to// complete, trigger onFinish without delayif (delay < 0) delay = 0;} else {delay = mCountdownInterval - lastTickDuration;// special case: user's onTick took more than interval to// complete, skip to next intervalwhile (delay < 0) delay += mCountdownInterval;}sendMessageDelayed(obtainMessage(MSG), delay);}}}};
}
WeakHandler类
public class WeakHandler extends Handler {private WeakReference<Activity> mActivity;public WeakHandler() {this(Looper.getMainLooper(), null);}public WeakHandler(@NonNull Looper looper) {this(looper, null);}public WeakHandler(@NonNull Looper looper, Activity mActivity) {super(looper);setActivity(mActivity);}public WeakReference<Activity> getActivity() {return mActivity;}public void setActivity(Activity mActivity) {this.mActivity = new WeakReference<>(mActivity);}
}
使用方法
private CountDownTimerRew mCountDownTimerRew;public CountDownTimerRew getCountDownTimerRew() {if (null == mCountDownTimerRew)mCountDownTimerRew = new CountDownTimerRew(5000, 1000) {@Overridepublic void onTick(long millisUntilFinished, Object mTag) {int iSeconds = (int) (millisUntilFinished / 1000);int iTag = mTag instanceof Integer ? (int) mTag : -1;if (iTag == 0) {//TODO}}@Overridepublic void onFinish() {}};return mCountDownTimerRew;}
//启动计时器
getCountDownTimerRew().setMillisInFuture(180000).setMillisInFuture(500).setTag(0).start();
//取消计时器
getCountDownTimerRew().cancel();