最近公司项目有需求在列表里添加一个30分钟倒计时订购的功能,跟普通发送验证码之类的倒计时不一样。有如下几个须要注意的地方java
1.在列表里作倒计时要避免闪烁以及性能的问题
2.跟验证码60秒等本地的倒计时不一样,时间比较长须要避免偏差。以及可能会屡次刷新
3.锁屏时不刷新或者Android省电机制致使的偏差
git
也可使用第三方库CountdownView。可是感受一个小功能本身作也能够。github
Android倒计时的实现方式能够看看博客Android 倒计时的五种实现方式 数组
在列表里作倒计时个人作法是在适配器里建立一个List集合用于保存要刷新的控件,而后建立一个方法刷新控件,核心代码以下bash
private List<TextView> tvPays = new ArrayList<>();
@Override
protected void convert(BaseViewHolder helper, HomePendingListBean item) {
```
TextView tv_pay = helper.getView(R.id.tv_pay);
if (!tvPays.contains(tv_pay)) {
tvPays.add(tv_pay);
}
```
}
public void resetNotifyTime() {
notifyTime = 0;
tvPays.clear();
}
public void notifyPay() {
notifyTime++;
for (int i = 0; i < tvPays.size(); i++) {
int expire_time = mData.get(i).getExpire_time() - notifyTime;
// int expire_time = mData.get(i).getExpire_time() - mData.get(i).getExpire_time();
String time = getRemainTime(expire_time);
if (expire_time<=0){
tvPays.get(i).setClickable(false);
tvPays.get(i).setText("("+ResourceUtils.getString(R.string.coupon_list_unvalid)+")");
}else{
tvPays.get(i).setText(time);
tvPays.get(i).setClickable(true);
}
}
}
复制代码
由于倒计时是统一一秒一秒的算的,因此我建立了个变量notifyTime
经过每次调用方法时++。而后根据后台返回的秒数减去notifyTime
就能实现计数,而且只新列表时只须要调用resetNotifyTime
把notifyTime
重置为0
便可从新计数。ide
而保存控件的List的做用是为了避免适用notify去刷新所有布局,虽然一开始以为这种作法不太好,不过比起每次去notify布局其实浪费点空间内存反而这种作法cpu损耗的可能更小一些。须要注意的是重置时要把List也清空一下避免后台返回为空时数组越界。布局
作到这里只须要在定时器的触发方法里调用adapter.notityPay()
方法便可。这里使用的adapter是BRVAH。很是好用,不知道的朋友能够看一下。post
我一开始使用的是Handle发送message的方式实现的定时器,这种方式是有偏差的。具体能够看看把倒计时作到极致 这篇文章。而且因为Android的省电机制在刷屏时Handle发送Message的方式会慢的一逼偏差异常大。因此我采用Rxjava的方式实现性能
private Disposable mTimeCountDisposable;
/**
* 倒计时
*
* @param count
*/
public void TimeCount(int count) {
if (mTimeCountDisposable != null) {
//取消上一次的订阅
mTimeCountDisposable.dispose();
}
//0-count依次输出,延时0s执行,每1s发射一次。
mTimeCountDisposable = Flowable.intervalRange(0, count, 0, 1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(aLong -> {
mHomePendingAdapter.notifyPay();
})
.doOnComplete(() -> {
if (mTimeCountDisposable != null)
mTimeCountDisposable.dispose();
})
.subscribe();
}
复制代码
这种作法通过测试几乎不存在什么偏差而且不会由于锁屏问题致使计时变慢,代码也相对简单,使用的是Rxjava2。这里跟第一篇推荐的文章Android 倒计时的五种实现方式 里面的有些不一样,这里使用Rxjava返回了一个Disposable。能够随时取消订阅。由于列表会屡次刷新,若是不取消订阅计时代码会存在多份,会影响列表的刷新。固然也不要忘了在onDestroy
里取消订阅。学习
@Override
public void onDestroy() {
super.onDestroy();
if (mTimeCountDisposable != null) {
mTimeCountDisposable.dispose();
}
}
复制代码
我以为使用Rxjava的方式实现代码是最少的,而且就性能来讲只是一个线程在后台应该不会损耗太多的性能,比起调用系统服务之类的反而我以为这个轻量一些。 关于锁屏其余解决方案能够本身去试一下。
1.使用系统的定时器而后作一个服务放到系统后台,而后使用广播通知界面。
2.使用系统定时器,注册一个刷屏广播计算刷屏到开屏的时间加上去。
3.让屏幕一直亮着。