Androidタイミング/カウントダウンツール-強化版CountDownTimer

8327 ワード

さぎょう
軽量級のAndroidタイミング/カウントダウンツール.
使用方法
  • start()カウントダウン
  • を開始
  • stop()カウントダウン
  • を停止
  • pause()カウントダウン
  • を一時停止
  • restart()中断を継続するカウントダウン
  • onTick()逆カウント時間間隔コールバック
  • onFinish()カウントダウン終了コールバック
  • CustomCountDownTimer(long millisInFuture,long countDownInterval)構造方法で、パラメータの意味:millisInFuture:総時間長countDownInterval:間隔時間長
  • たとえば、CustomCountDownTimer(1000000,000)は、これからカウントダウンを開始し、10秒後に終了し、onTickイベントを毎秒1回トリガーすることを示します.注意:onTickイベントは、毎秒の開始時刻に呼び出されます.すなわち、「onTick-1秒」-「onTick-1秒」......を10回繰り返します.
    ソースコード
    import android.os.Handler;
    import android.os.Message;
    import android.os.SystemClock;
    
    /**
     *    android.os.CountDownTimer    
     * 1.     onTick       ,     1       0,   2     onFinish
     * 2.           
     * Created by iWgang on 15/10/18.
     * https://github.com/iwgang/CountdownView
     */
    public abstract class CustomCountDownTimer {
    
        private static final long ONE_SECOND_MILLS = 1000L;
        private static final long CORRECT_OFFSET = 15L;
    
        private static final int MSG = 1;
        private final long mMillisInFuture;
        private final long mCountdownInterval;
        private long mStopTimeInFuture;
        private long mPauseTimeInFuture;
        private boolean isStop = false;
        private boolean isPause = false;
    
        /**
         * @param millisInFuture          
         * @param countDownInterval        
         */
        public CustomCountDownTimer(long millisInFuture, long countDownInterval) {
            //               2   ( 10    ,    8999,        9 ,   8 )
            if (countDownInterval > ONE_SECOND_MILLS) {
                millisInFuture += CORRECT_OFFSET;
            }
            mMillisInFuture = millisInFuture;
            mCountdownInterval = countDownInterval;
        }
    
        private synchronized CustomCountDownTimer start(long millisInFuture) {
            isStop = false;
            if (millisInFuture <= 0) {
                onFinish();
                return this;
            }
            mStopTimeInFuture = SystemClock.elapsedRealtime() + millisInFuture;
            mHandler.sendMessage(mHandler.obtainMessage(MSG));
            return this;
        }
    
        /**
         *      
         */
        public synchronized final void start() {
            start(mMillisInFuture);
        }
    
        /**
         *      
         */
        public synchronized final void stop() {
            isStop = true;
            mHandler.removeMessages(MSG);
        }
    
        /**
         *      
         *   {@link #restart()}      
         */
        public synchronized final void pause() {
            if (isStop) return;
    
            isPause = true;
            mPauseTimeInFuture = mStopTimeInFuture - SystemClock.elapsedRealtime();
            mHandler.removeMessages(MSG);
        }
    
        /**
         *     
         */
        public synchronized final void restart() {
            if (isStop || !isPause) return;
    
            isPause = false;
            start(mPauseTimeInFuture);
        }
    
        /**
         *        
         *
         * @param millisUntilFinished      
         */
        public abstract void onTick(long millisUntilFinished);
    
        /**
         *        
         */
        public abstract void onFinish();
    
    
        private Handler mHandler = new Handler() {
    
            @Override
            public void handleMessage(Message msg) {
    
                synchronized (CustomCountDownTimer.this) {
                    if (isStop || isPause) {
                        return;
                    }
    
                    final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
                    if (millisLeft <= 0) {
                        onFinish();
                    }
                    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);
                    }
                }
            }
        };
    }