美文网首页
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