Back

android - 实现定时刷新页面:使用CountDownTimer

发布时间: 2017-09-01 23:22:00

参考:  https://stackoverflow.com/questions/21726055/android-loop-part-of-the-code-every-5-seconds 和 https://stackoverflow.com/questions/8278041/how-to-create-an-infinite-loop

完整的例子如下: (一反短平快的博客风格,还是记录下来吧,这里有点儿坑。例子之后是几个讲解的注意点)
补充:实在是太坑了.... 

public class YourActivity ... { 
    private CountDownTimer countDownTimer;
    private long AUTO_REFRESH_INTERVAL = 10000;   // 10秒执行一次。常量。


    // 初始化方法
    public void onCreate(){
        startCountDownTimer(); 
    }

    //  初始化并且启动count down timer. 
    private void startCountDownTimer(){
        // 注意这里要做个非空判断。
        if(countDownTimer == null){
            countDownTimer = new CountDownTimer(600 * AUTO_REFRESH_INTERVAL, AUTO_REFRESH_INTERVAL) {
                @Override
                public void onTick(long millisUntilFinished) {
                    Log.d(TAG, "== in CountDownTimer, onTick, refreshData... ");
                    refreshData(false);
                }

                @Override
                public void onFinish() {
                    Log.d(TAG, "== in CountDownTimer, countDownTimer, onFinish");
                    // start again.
                    start();
                }
            };
        }

        restartCountDownTimer();
    }

    // 重新启动. 
    private void restartCountDownTimer(){
        countDownTimer.cancel();
   //首次计数器会被立刻触发。所以 延后特定的时间来执行。 
    // (注意:不要这样做,会导致有 timer.start()的两个方法再跑。(同一个对象,运行两个方法,应该是多线程。。。无语了)
    // 应该直接 countDownTimer.start()就好。
/*
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                countDownTimer.start();
            }
        }, AUTO_REFRESH_INTERVAL);
*/
        countDownTimer.start();
    }

    // 记得这里要修改。如果你的是Fragment的话,在第一次显示的时候,这个方法就会被触发。
    public void onResume(){
       countDownTimer.cancel();
       countDownTimer.start()  
    }

    private void refreshData(final boolean isManuallyExecuted) { 
        // ...
       // 手动刷新后,下次10秒后才会自动刷新
                            if(isManuallyExecuted){
                                restartCountDownTimer();
                            }
    }

添加如下代码:

private CountDownTimer countDownTimer;

        // 第一个参数是定时器执行的总时间,第二个参数是每隔多久,就触发一次 onTick
        countDownTimer = new CountDownTimer(600000, 10000) {
            @Override
            public void onTick(long millisUntilFinished) {
                Log.d(TAG, "== in CountDownTimer, onTick");
                refreshData( false );  // 注意这里的参数,false 表示:“不是手动触发” 
            }

            // 定时器结束后,自动重启。
            @Override
            public void onFinish() {
                Log.d(TAG, "== in CountDownTimer, countDownTimer, onFinish");
                // start again.
                start();
            }
        }.start();

注意1:  很多时候,手动刷新之后,需要重置 定时器:

                            // 手动刷新后,下次10秒后才会自动刷新
                            if(isManuallyExecuted){
                                countDownTimer.cancel();
                                new Handler().postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        countDownTimer.start();
                                    }
                                }, 10000);
                            }

所有有上述代码。

注意2: 在首次启动时, 要延后一段时间执行,并且要区分被执行的方法“是不是手动触发”。如果不区分的话, 就会陷入到 “counter调用自动方法,立刻执行,该方法执行完毕后,重启counter,  该counter调用自动方法,立刻执行。。。" 是个死循环

注意3:根据实际观察,如果定义了第二个参数是10000, 我们发现被触发的时间,会延后10毫秒。

日志:

09-02 07:23:51.403 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:24:01.403 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:24:11.413 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:24:21.433 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:24:31.443 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:24:41.433 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:24:51.453 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:25:01.463 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:25:11.473 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:25:21.473 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:25:31.483 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:25:41.513 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:25:51.533 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:26:01.543 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:26:11.553 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick
09-02 07:26:21.553 8090-8090/com.yunbi D/MarketFragmentN: == in CountDownTimer, onTick

所以,如果你的一个定时任务,每隔10秒执行一次的话,如果把总时间设置成20秒,就会发现该任务只会触发一次。 原因是20秒内不会出现两次。估计需要20.1秒,才能成功触发两次。 

为了弥补这个缺陷,建议把总时间设置的长一些

Back