android的CountDownTimer开始时间不准或者不能倒计时到0的一种解决思路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010898329/article/details/75005814

很多情况下,android需要使用倒计时的功能,网上有许多的实现方式,在这里我来跟大家讨论下android的CountDownTimer这个类的实际使用。

CountDownTimer这个类的使用非常的简单。

new CountDownTimer(countTime , internal){

    @Override
    public void onTick(long l) {
        // 每隔internal毫秒就会回调一次该方法
        
    }

    @Override
    public void onFinish() {
        // 当countTime倒计时到了之后,会回调该方法
        
    }
}.start(); // 最后记得start


传两个参数就可以了。下面看下我在实际使用中的坑,有图有真相


不知道有没有看出异常,就是下面的两个BUG!!!!!!!!


为了以证清白我,我把我的代码都帖出来

public class CountTimerActivity extends AppCompatActivity implements View.OnClickListener{

    private int mCount = 20 ;

    private TextView countTv ;

    private Button start , stop ;

    CountDownTimer countDownTimer ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_count_timer);

        start = (Button) findViewById(R.id.start);
        stop = (Button)findViewById(R.id.stop);
        countTv = (TextView) findViewById(R.id.time);

        getSupportActionBar().setTitle("倒计时测试");

        countDownTimer = new CountDownTimer(mCount*1000 , 1000) {
            @Override
            public void onTick(long l) {
                Log.d("CJT", "onTick----l=="+l);
                countTv.setText((int)l/1000+" 秒");
            }

            @Override
            public void onFinish() {
                Log.d("CJT", "onFinish-------");
                countTv.setText("finish!");
            }
        };

        start.setOnClickListener(this);
        stop.setOnClickListener(this);
        
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.start:
                countDownTimer.start();
                break;
            case R.id.stop:
                countDownTimer.cancel();
                break;
        }
    }

    @Override
    protected void onDestroy() {
        if(countDownTimer != null )
            countDownTimer.cancel();
        super.onDestroy();
    }
}

按照常规的使用方法却出现了意想不到的BUG,当然程序是死的,人是活的,总有办法看可以解决的。

一、下面看下怎么解决第一个BUG:时间直接从20秒倒计时跳到了18秒?

出现这个问题的主要原因是我们在onTick(long l)中取到的l有误差,理论上应该从20000减去1000变为19000 ,可是打印结果却是18999,这1毫秒的误差导致在强制类型转换少了1秒,而且随着onTick方法不断回调,这个误差也越来越大,在20秒的时间中相差了2000-1982=8毫秒(最后一次打印,理论值2000,实际值1982)。

明白了这个问题出现的原因就好解决了,直接将原来的countTime补上这个误差就可以了


看下运行的Log

07-12 18:33:32.417 4724-4724/com.cjt.testvolley D/CJT: onTick----l==20050
07-12 18:33:33.417 4724-4724/com.cjt.testvolley D/CJT: onTick----l==19049
07-12 18:33:34.417 4724-4724/com.cjt.testvolley D/CJT: onTick----l==18048
07-12 18:33:35.417 4724-4724/com.cjt.testvolley D/CJT: onTick----l==17046
07-12 18:33:36.417 4724-4724/com.cjt.testvolley D/CJT: onTick----l==16045
07-12 18:33:37.417 4724-4724/com.cjt.testvolley D/CJT: onTick----l==15044
07-12 18:33:38.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==14042
07-12 18:33:39.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==13041
07-12 18:33:40.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==12040
07-12 18:33:41.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==11038
07-12 18:33:42.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==10036
07-12 18:33:43.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==9035
07-12 18:33:44.437 4724-4724/com.cjt.testvolley D/CJT: onTick----l==8034
07-12 18:33:45.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==7033
07-12 18:33:46.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==6033
07-12 18:33:47.427 4724-4724/com.cjt.testvolley D/CJT: onTick----l==5032
07-12 18:33:48.436 4724-4724/com.cjt.testvolley D/CJT: onTick----l==4031
07-12 18:33:49.436 4724-4724/com.cjt.testvolley D/CJT: onTick----l==3030
07-12 18:33:50.436 4724-4724/com.cjt.testvolley D/CJT: onTick----l==2029
07-12 18:33:51.436 4724-4724/com.cjt.testvolley D/CJT: onTick----l==1027
07-12 18:33:52.466 4724-4724/com.cjt.testvolley D/CJT: onFinish-------

运行还算正常,而且强转之后绝对不会出错了!


二、下面看下怎么解决第二个BUG:时间怎么不到0?

出现这个问题的主要原因是我认为是在onTick(long l)中取到的l减去internal(我们设定的间隔时间)还比internal小的时候,会回调onFinsh()方法,而不再回调onTick()方法了,有小伙伴在想是否可以在onFinis()方法中直接设置文本框为0秒呢?我试过,但是不起作用的,对这个有兴趣的可以去研究下。还是回到这个问题,我们是为了解决为何不显示0,还有其他的方法可以搞定的嘛!我呢,还是在总时间上动手脚,不过这次是直接加1000毫秒,在显示的时候减去这一秒,具体操作如下。


这样改动之后下面看下最后的效果:




好了,基本上实现了想要的效果,也用另一种方式解决了两个BUG,注意这里的误差时间不一定是50毫秒,要根据实际情况来定,有可能要设定的更大才行。


最后修改后的代码,主要部分


countDownTimer = new CountDownTimer(mCount*1000 + 1050 , 1000) {
    @Override
    public void onTick(long l) {
        Log.d("CJT", "onTick----l=="+l);
        countTv.setText(((int)l/1000 -1)+" 秒");
    }

    @Override
    public void onFinish() {
        Log.d("CJT", "onFinish-------");
        countTv.setText("finish!");
    }
};



猜你喜欢

转载自blog.csdn.net/u010898329/article/details/75005814