最近公司項目有需求在列表裏添加一個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.讓屏幕一直亮着。