美文网首页
Android CountDownTimer使用注意

Android CountDownTimer使用注意

作者: yunhen | 来源:发表于2021-12-22 13:28 被阅读0次

    注意: 需要在主线程里调用 .start() ,否则没效果

    import android.os.Handler;
    import android.os.Looper;
    
    /**
     * Created by dongqi on 2021/12/21.
     */
    public class MCountDownTimer {
        private static final String TAG = MCountDownTimer.class.getSimpleName();
        private MyCountDownTimerCompat countDownTimer;
        private long mMillisInFuture;
        private long mCountDownInterval;
        private Handler mainHandler = new Handler(Looper.getMainLooper());
    
        /**
         * 不是单例,每次都会创建新对象 (CountDownTimer)
         * @return
         */
        public static MCountDownTimer getCountDownTimer(){
            return new MCountDownTimer() ;
        }
    
        /**
         * 总时长
         * @param millisInFuture
         * @return
         */
        public MCountDownTimer setMillisInFuture(long millisInFuture){
            mMillisInFuture = millisInFuture;
            return this;
        }
    
        /**
         * 间隔时长
         * @param countDownInterval
         * @return
         */
        public MCountDownTimer setCountDownInterval(long countDownInterval){
            mCountDownInterval = countDownInterval;
            return this;
        }
        OnTickCallback mOnTickCallback;
        public MCountDownTimer setOnTick(OnTickCallback onTickCallback){
            mOnTickCallback = onTickCallback;
            return this;
        }
    
        public interface OnTickCallback{
            void onTick(long millisUntilFinished) ;
        }
    
        public interface OnFinishCallback{
            void onFinish() ;
        }
    
        public interface OnCancelCallback{
            void onCancel() ;
        }
        OnCancelCallback mOnCancelCallback;
        public MCountDownTimer setOnCancel(OnCancelCallback onCancelCallback){
            mOnCancelCallback = onCancelCallback;
            return this;
        }
    
    
        OnFinishCallback mOnFinishCallback;
        public MCountDownTimer setOnFinish(OnFinishCallback onFinishCallback){
            mOnFinishCallback = onFinishCallback;
            return this;
        }
    
    
        public MCountDownTimer() {
            if (mainHandler == null)
                mainHandler = new Handler(Looper.getMainLooper());
        }
    
    
        /**
         * 创建 CountDownTimer ,并调用 start 函数
         */
        public void start(){
            L.d(TAG," start 1");
    
            L.d(TAG," start 1 mMillisInFuture = "+mMillisInFuture);
            L.d(TAG," start 1 mCountDownInterval = "+mCountDownInterval);
    
            if (mainHandler == null)
                throw new NullPointerException("start() 中的 mainHandler 是 null!!! ");
    
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    countDownTimer = new MyCountDownTimerCompat(mMillisInFuture,mCountDownInterval) {
                        @Override
                        public void onTick(long millisUntilFinished) {
                            L.d(TAG," onTick millisUntilFinished ="+millisUntilFinished);
                            if (mOnTickCallback!= null)
                                mOnTickCallback.onTick(millisUntilFinished);
                        }
    
                        @Override
                        public void onFinish() {
                            L.d(TAG," onFinish ");
                            if (mOnFinishCallback!=null)
                                mOnFinishCallback.onFinish();
    
                        }
    
                        @Override
                        public void onCancel() {
                            if (mOnCancelCallback!=null)
                                mOnCancelCallback.onCancel();
                        }
                    };
                    if (countDownTimer == null) {
                        L.d(TAG," start 2 countDownTimer null !!!");
                    }else {
                        countDownTimer.start();
                    }
                    L.d(TAG," start 2");
                }
            });
    
        }
    
    
        public void cancel(){
            if (countDownTimer != null) {
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        countDownTimer.cancel();
                    }
                });
            }
    
        }
    
    }
    

    因为android5.0以下,取消函数没有效果,所以复制了一份CountDownTimer高版本的源码出来到放到 MyCountDownTimerCompat 里;并且增加啦 onCancel回调接口

    import android.os.Handler;
    import android.os.Message;
    import android.os.SystemClock;
    
    import java.lang.ref.WeakReference;
    
    /**
     * Created by wanghh on 16/9/6.
     */
    public abstract class MyCountDownTimerCompat {
    
        /**
         * Millis since epoch when alarm should stopSpeaking.
         */
        private final long mMillisInFuture;
    
        /**
         * The interval in millis that the user receives callbacks
         */
        private final long mCountdownInterval;
    
        private long mStopTimeInFuture;
    
        /**
         * boolean representing if the timer was cancelled
         */
        private boolean mCancelled = false;
    
        /**
         * @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)} callbacks.
         */
        public MyCountDownTimerCompat(long millisInFuture, long countDownInterval) {
            mMillisInFuture = millisInFuture;
            mCountdownInterval = countDownInterval;
        }
    
        /**
         * Cancel the countdown.
         */
        public synchronized final void cancel() {
            mCancelled = true;
            mHandler.removeMessages(MSG);
        }
    
        /**
         * Start the countdown.
         */
        public synchronized final MyCountDownTimerCompat 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);
    
        /**
         * Callback fired when the time is up.
         */
        public abstract void onFinish();
    
        public abstract void onCancel();
    
    
        private static final int MSG = 1;
    
        static class MyHandler extends Handler {
            private WeakReference<MyCountDownTimerCompat> mOuter;
    
            public MyHandler(MyCountDownTimerCompat myCountDownTimerCompat) {
                mOuter = new WeakReference<MyCountDownTimerCompat>(myCountDownTimerCompat);
            }
    
            @Override
            public void handleMessage(Message msg) {
                MyCountDownTimerCompat outer = mOuter.get();
                if (null != outer) {
                    synchronized (MyCountDownTimerCompat.class) {
                        if (outer.mCancelled) {
                            outer.onCancel();
                            return;
                        }
    
                        final long millisLeft = outer.mStopTimeInFuture - SystemClock.elapsedRealtime();
    
                        if (millisLeft <= 0) {
                            outer.onFinish();
                        } else if (millisLeft < outer.mCountdownInterval) {
                            // no tick, just delay until done
                            sendMessageDelayed(obtainMessage(MSG), millisLeft);
                        } else {
                            long lastTickStart = SystemClock.elapsedRealtime();
                            outer.onTick(millisLeft);
    
                            // take into account user's onTick taking time to execute
                            long delay = lastTickStart + outer.mCountdownInterval - SystemClock.elapsedRealtime();
    
                            // special case: user's onTick took more than interval to
                            // complete, skip to next interval
                            while (delay < 0) delay += outer.mCountdownInterval;
    
                            sendMessageDelayed(obtainMessage(MSG), delay);
                        }
                    }
                }
    //            super.handleMessage(msg);
            }
        }
    
        private MyHandler mHandler = new MyHandler(MyCountDownTimerCompat.this);
    
        // handles counting down
    //    private Handler mHandler = new Handler() {
    //
    //        @Override
    //        public void handleMessage(Message msg) {
    //
    //            synchronized (MyCountDownTimer.this) {
    //                if (mCancelled) {
    //                    onCancel();
    //                    return;
    //                }
    //
    //                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
    //
    //                if (millisLeft <= 0) {
    //                    onFinish();
    //                } else if (millisLeft < mCountdownInterval) {
    //                    // no tick, just delay until done
    //                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
    //                } else {
    //                    long lastTickStart = SystemClock.elapsedRealtime();
    //                    onTick(millisLeft);
    //
    //                    // take into account user's onTick taking time to execute
    //                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
    //
    //                    // special case: user's onTick took more than interval to
    //                    // complete, skip to next interval
    //                    while (delay < 0) delay += mCountdownInterval;
    //
    //                    sendMessageDelayed(obtainMessage(MSG), delay);
    //                }
    //            }
    //        }
    //    };
    }
    

    相关文章

      网友评论

          本文标题:Android CountDownTimer使用注意

          本文链接:https://www.haomeiwen.com/subject/ipyqqrtx.html