av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

解決Android-RecyclerView列表倒計(jì)時(shí)錯(cuò)亂問(wèn)題

瀏覽:100日期:2022-09-22 18:38:06

前言

轉(zhuǎn)眼間距離上次寫博客已是過(guò)了一個(gè)年輪,期間發(fā)生了不少事;經(jīng)歷了離職、找工作,新公司的第一版項(xiàng)目上線。現(xiàn)在總算是有時(shí)間可以將遇到的問(wèn)題梳理下了,后期有時(shí)間也會(huì)分享更多的東西~~

場(chǎng)景

今天分享的問(wèn)題是當(dāng)在列表里面顯示倒計(jì)時(shí),這時(shí)候滑動(dòng)列表會(huì)出現(xiàn)時(shí)間顯示不正常的問(wèn)題。首先關(guān)于倒計(jì)時(shí)我們需要注意的問(wèn)題有以下幾方面:

在RecyclerView中ViewHolder的復(fù)用導(dǎo)致的時(shí)間亂跳的問(wèn)題。

滑動(dòng)列表時(shí)倒計(jì)時(shí)會(huì)重置的問(wèn)題。

在退出頁(yè)面后定時(shí)器的資源釋放問(wèn)題,這里我使用的是用系統(tǒng)自帶的CountDownTimer

ps:這里我們討論的是對(duì)倒計(jì)時(shí)要求不是很嚴(yán)格的場(chǎng)景,對(duì)于用戶手動(dòng)修改系統(tǒng)時(shí)間這種操作沒(méi)法預(yù)計(jì);對(duì)于淘寶秒殺這種業(yè)務(wù)場(chǎng)景建議是實(shí)時(shí)不斷請(qǐng)求后臺(tái)拿取正確時(shí)間,對(duì)應(yīng)的接口盡量設(shè)計(jì)簡(jiǎn)單,響應(yīng)數(shù)據(jù)更快。

接下來(lái)通過(guò)代碼具體了解:

代碼

// 適配器public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { //服務(wù)器返回?cái)?shù)據(jù) private List<TimeBean> mDatas; //退出activity時(shí)關(guān)閉所有定時(shí)器,避免造成資源泄漏。 private SparseArray<CountDownTimer> countDownMap; //記錄每次刷新時(shí)的時(shí)間 private long tempTime; public MyAdapter(Context context, List<TimeBean> datas) { mDatas = datas; countDownMap = new SparseArray<>(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_common, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, int position) { final TimeBean data = mDatas.get(position); //記錄時(shí)間點(diǎn) long timeStamp = System.currentTimeMillis() - tempTime; long time = data.getLeftTime() - timeStamp; //將前一個(gè)緩存清除 if (holder.countDownTimer != null) { holder.countDownTimer.cancel(); } if (time > 0) { //判斷倒計(jì)時(shí)是否結(jié)束 holder.countDownTimer = new CountDownTimer(time, 1000) {public void onTick(long millisUntilFinished) { holder.timeTv.setText(getMinuteSecond(millisUntilFinished));}public void onFinish() { //倒計(jì)時(shí)結(jié)束 holder.timeTv.setText('00:00');} }.start(); countDownMap.put(holder.timeTv.hashCode(), holder.countDownTimer); } else { holder.timeTv.setText('00:00'); } } @Override public int getItemCount() { if (mDatas != null && !mDatas.isEmpty()) { return mDatas.size(); } return 0; } public class ViewHolder extends RecyclerView.ViewHolder { public TextView timeTv; public CountDownTimer countDownTimer; public ViewHolder(View itemView) { super(itemView); timeTv = (TextView) itemView.findViewById(R.id.tv_time); } } public void setGetTime(long tempTime) { this.tempTime = tempTime; } /** * 將毫秒數(shù)換算成 00:00 形式 */ public static String getMinuteSecond(long time) { int ss = 1000; int mi = ss * 60; int hh = mi * 60; int dd = hh * 24; long day = time / dd; long hour = (time - day * dd) / hh; long minute = (time - day * dd - hour * hh) / mi; long second = (time - day * dd - hour * hh - minute * mi) / ss; String strMinute = minute < 10 ? '0' + minute : '' + minute; String strSecond = second < 10 ? '0' + second : '' + second; return strMinute + ':' + strSecond; } /** * 清空資源 */ public void cancelAllTimers() { if (countDownMap == null) { return; } for (int i = 0,length = countDownMap.size(); i < length; i++) { CountDownTimer cdt = countDownMap.get(countDownMap.keyAt(i)); if (cdt != null) {cdt.cancel(); } } }}

以上算是整個(gè)問(wèn)題的核心代碼了;其中SparseArray<CountDownTimer> 用來(lái)保存列表里面的定時(shí)器,用于退出頁(yè)面時(shí)回收定時(shí)器。SparseArray是安卓特有的數(shù)據(jù)結(jié)構(gòu),建議多使用;data.getLeftTime() 是服務(wù)器返回的需要倒計(jì)時(shí)的時(shí)間,毫秒為單位。

問(wèn)題一:ViewHolder的復(fù)用導(dǎo)致的數(shù)據(jù)錯(cuò)亂

if (holder.countDownTimer != null) { holder.countDownTimer.cancel(); }

每次設(shè)置倒計(jì)時(shí)之前重置下倒計(jì)時(shí)即可解決。

問(wèn)題二:滑動(dòng)列表時(shí)倒計(jì)時(shí)會(huì)重置的問(wèn)題

這個(gè)問(wèn)題是由于解決問(wèn)題一而導(dǎo)致的,因?yàn)榱斜砘瑒?dòng)時(shí)離開(kāi)屏幕的會(huì)被復(fù)用,這個(gè)時(shí)候我們會(huì)重新設(shè)置定時(shí)器,之前我是在倒計(jì)時(shí)里面記錄倒計(jì)時(shí)剩余的時(shí)間然后重新設(shè)值,但是還是會(huì)有問(wèn)題;這里借用了系統(tǒng)時(shí)間來(lái)解決,也就是tempTime 這個(gè)值。

首先在服務(wù)器請(qǐng)求成功后回調(diào)里面設(shè)置這個(gè)值,如:

private MyAdapter adapter; @Override public void onHttpRequestSuccess(String url, HttpContext httpContext) { if (服務(wù)器返回?cái)?shù)據(jù)) { adapter.setGetTime(System.currentTimeMillis()); }

相當(dāng)于每次做刷新操作時(shí)獲取的都是系統(tǒng)當(dāng)時(shí)的時(shí)間戳。

然后在adapter里面計(jì)算

long timeStamp = System.currentTimeMillis() - tempTime;

long time = data.getLeftTime() - timeStamp;

其中tempTime就是我們保存的系統(tǒng)當(dāng)前時(shí)間戳,然后每次滑動(dòng)列表時(shí)都會(huì)調(diào)用onBindViewHolder,所以timeStamp就是記錄的距離上次刷新經(jīng)過(guò)了多少秒,然后用服務(wù)器返回的需要倒計(jì)時(shí)的時(shí)間減去經(jīng)過(guò)的秒數(shù)就是還剩下的倒計(jì)時(shí)秒數(shù)。最后給定時(shí)器設(shè)置上就好了。

問(wèn)題三:資源的釋放

在當(dāng)前的activity中調(diào)用以下方法。

@Overrideprotected void onDestroy() { super.onDestroy(); if (adapter != null) { adapter.cancelAllTimers(); }}

好了,今天的分享就到這了,因?yàn)榇a比較簡(jiǎn)單,布局都是一個(gè)Textview,所以沒(méi)有貼出來(lái),需要代碼的可以留言~~

補(bǔ)充知識(shí):Android 自定義倒計(jì)時(shí),支持listview多item一起倒計(jì)時(shí)

項(xiàng)目中用到的兩種倒計(jì)時(shí),一種是用CountDownTimer,但是這種方式在listview中就不是那么好用了,當(dāng)listview 里面多個(gè)item都需要倒計(jì)時(shí),就不可以用這種了,我這里想到用Thread 加handler來(lái)一起實(shí)現(xiàn)。如果大家還有好的倒計(jì)時(shí)方法,可以留言一起討論哦,由于代碼都是在項(xiàng)目中的,我就截取幾段代碼。

第一種 CountDownTimer:

主要自定義一個(gè)類繼承CountDownTimer,在啟動(dòng)的時(shí)候調(diào)用start(),倒計(jì)時(shí)完畢調(diào)用canel()方法。

time = new TimeCount(remainingTime, 1000);//構(gòu)造CountDownTimer對(duì)象time.start();//開(kāi)始計(jì)時(shí)class TimeCount extends CountDownTimer { public TimeCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onFinish() {//計(jì)時(shí)完畢時(shí)觸發(fā) if (isDead) {remainingTime = 90000;ColorStateList colorStateList = getResources().getColorStateList(R.color.button_send_code_text2_selector);getCode.setTextColor(colorStateList);getCode.setText(R.string.register_tip7);getCode.setEnabled(true); } } @Override public void onTick(long millisUntilFinished) {//計(jì)時(shí)過(guò)程顯示 if (isDead) {getCode.setEnabled(false);getCode.setTextColor(getResources().getColor(R.color.grey5));remainingTime = millisUntilFinished;getCode.setText(millisUntilFinished / 1000 + '秒后重發(fā)'); } } }

第二種 Thread 加handler

創(chuàng)建一個(gè)新的線程,每秒中減一次時(shí)間,然后在handler中每秒中刷新一次界面就可以看到倒計(jì)時(shí)的效果。

private Thread thread; //條目倒計(jì)時(shí) public void start() { thread = new Thread() { public void run() {while (true) { try { if (list != null) { for (InvestProjectVo item : list) {if(item.remainOpenTime == 0){ item.status = 0;}if(item.remainOpenTime > 0){ item.remainOpenTime = item.remainOpenTime - 1;} } } sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }} } }; thread.start(); }

在adapter的getview()方法中,判斷倒計(jì)時(shí)時(shí)間是否大于0,如果大于零可以繼續(xù)顯示倒計(jì)時(shí)時(shí)間

if (vo.remainOpenTime != 0 && vo.remainOpenTime > 0) { viewCache.showProjectFullIcon.setVisibility(View.GONE); viewCache.projectProgress.setVisibility(View.GONE); viewCache.showTimer.setVisibility(View.VISIBLE); long tempTime = vo.remainOpenTime; long day = tempTime / 60 / 60 / 24; long hours = (tempTime - day * 24 * 60 * 60) / 60 / 60; long minutes = (tempTime - day * 24 * 60 * 60 - hours * 60 * 60) / 60; long seconds = (tempTime - day * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60); if (minutes > 0) { viewCache.timer.setText(minutes + '分' + seconds + '秒'); } else { viewCache.timer.setText(seconds + '秒'); } }else{ viewCache.showProjectFullIcon.setVisibility(View.GONE); viewCache.projectProgress.setVisibility(View.VISIBLE); viewCache.showTimer.setVisibility(View.GONE); }

在handler中每秒鐘刷新一次界面

mHandler.sendEmptyMessageDelayed(2586221,1000);

adapter.notifyDataSetChanged();//每隔1毫秒更新一次界面,如果只需要精確到秒的倒計(jì)時(shí)此處改成1000即可mHandler.sendEmptyMessageDelayed(2586221,1000);

以上這篇解決Android-RecyclerView列表倒計(jì)時(shí)錯(cuò)亂問(wèn)題就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 99国产精品久久久久久久 | 亚洲一区二区视频在线播放 | 日本不卡一区二区三区 | 成人a网| 日本亚洲欧美 | 91精品国产欧美一区二区 | 久久久国产网站 | 日本不卡高字幕在线2019 | 国产在线一区二区 | 亚洲精品久久久蜜桃网站 | 人人射人人草 | 伊人网站在线 | 国产午夜精品一区二区三区在线观看 | 午夜在线精品偷拍 | 中文一区 | k8久久久一区二区三区 | 性色视频在线观看 | 欧美日韩在线观看一区 | 国产日产久久高清欧美一区 | 国产精品欧美一区二区 | 国产激情精品视频 | 国产极品粉嫩美女呻吟在线看人 | 最新av在线播放 | 九七午夜剧场福利写真 | 欧美在线亚洲 | 欧美国产激情二区三区 | 精品国产欧美一区二区三区不卡 | 韩三级在线观看 | 成人精品国产免费网站 | 免费一二区 | 日本成人福利 | 91视频.com| 久久久99国产精品免费 | 亚洲性人人天天夜夜摸 | 欧美日韩亚洲视频 | 特黄特色大片免费视频观看 | 精品一区二区在线看 | 亚洲成人精品一区 | 99精品国产一区二区青青牛奶 | 欧美日韩精品一区二区 | 91精品国产91久久久久游泳池 |