您的位置:首页 > 移动开发 > Android开发

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

2017-07-12 10:10 561 查看
很多情况下,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!");
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐