Android開發(fā)之ListView實(shí)現(xiàn)Item局部刷新
對于android中的ListView刷新機(jī)制,大多數(shù)的程序員都是很熟悉的,修改或者添加adapter中的數(shù)據(jù)源之后,然后調(diào)用notifyDataSetChanged()刷新ListView。在這種模式下,我們會(huì)在getView中,根據(jù)不同的數(shù)據(jù)源,讓控件顯示不同的內(nèi)容。這種模式是最常見的刷新模式,當(dāng)我們來回滑動(dòng)ListView的時(shí)候,調(diào)用adapter的getView方法,然后listview對adapter返回的View進(jìn)行繪制。這種模式下,View的顯示內(nèi)容或狀態(tài)都記錄在adapter里面的數(shù)據(jù)源中,listview的更新頻率不頻繁,它隨著數(shù)據(jù)源的變化而更新。
但是腳本之家小編在做公司項(xiàng)目的時(shí)候,有個(gè)下載模塊,因?yàn)榭赡芡瑫r(shí)下載好幾個(gè)數(shù)據(jù),所以用的listview展示所有正在下載的內(nèi)容。因?yàn)橄螺d進(jìn)度要實(shí)時(shí)更新,所以要不停的調(diào)用notifyDateSetChanged刷新數(shù)據(jù)。這樣會(huì)不停的重新繪制整個(gè)listview的界面,性能開銷非常大。而且如果每個(gè)item有圖片的話,每個(gè)item的圖片都需要重新加載,就算圖片做了內(nèi)存緩存,刷新一下圖片也會(huì)閃一下,不停的刷新就會(huì)導(dǎo)致各個(gè)item的圖片不停的閃,體驗(yàn)一點(diǎn)都不好。
那么對于上面問題,有沒有解決辦法呢?當(dāng)然是有的。我們可以針對某一個(gè)item進(jìn)行局部更新,而不影響其它沒有修改的item。那么具體如何實(shí)現(xiàn)的呢?我們看下面的代碼。
private void updateView(int itemIndex) { //得到第一個(gè)可顯示控件的位置, int visiblePosition = mListView.getFirstVisiblePosition(); //只有當(dāng)要更新的view在可見的位置時(shí)才更新,不可見時(shí),跳過不更新 if (itemIndex - visiblePosition >= ) { //得到要更新的item的view View view = mListView.getChildAt(itemIndex - visiblePosition); //調(diào)用adapter更新界面 mAdapter.updateView(view, itemIndex); } }
這個(gè)函數(shù)主要是根據(jù)傳入的itemIndex來獲取第itemIndex的數(shù)據(jù)所顯示的view。itemIndex就是要修改的數(shù)據(jù)再List集合中的位置,比如我這里下載進(jìn)度有更新,發(fā)了一個(gè)廣播這里接收到了,需要修改該下載內(nèi)容的進(jìn)度條,廣播接收器可以這么寫:
@Override public void onReceive(Context context, Intent intent) { AppContent appContent = intent.getParcelableExtra("appContent"); if(appContent == null) return; int itemIndex = ; for(AppContent appContent : mList) { if(appContent.getUrl().equals(appContent.getUrl())) { itemIndex = mList.indexOf(appContent); appContent.setDownloadPercent(appContent.getDownloadPercent()); break; } } updateView(itemIndex); }
下面看Adapter的具體代碼:
public class AppContentAdapter extends BaseAdapter{ private List<AppContent> mDates = null; private Context mContext; public AppContentAdapter(Context context) { this.mContext = context; } @Override public int getCount() { return mDates.size(); } @Override public Object getItem(int position) { return mDates.get(position); } @Override public long getItemId(int position) { return position; } public void setDates(List<AppContent> mDates) { this.mDates = mDates; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(mContext).inflate( R.layout.listitem_download, null); holder.statusIcon = (DownloadPercentView) convertView.findViewById(R.id.status_icon); holder.name = (TextView) convertView.findViewById(R.id.name); holder.downloadPercent = (TextView) convertView.findViewById(R.id.download_percent); holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progressbar); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } setData(holder, position); return convertView; } /** * 設(shè)置viewHolder的數(shù)據(jù) * @param holder * @param itemIndex */ private void setData(ViewHolder holder, int itemIndex) { AppContent appContent = mDates.get(itemIndex); holder.name.setText(appContent.getName()); holder.progressBar.setProgress(appContent.getDownloadPercent()); setIconByStatus(holder.statusIcon, appContent.getStatus()); if(appContent.getStatus() == AppContent.Status.PENDING) { holder.downloadPercent.setVisibility(View.INVISIBLE); } else { holder.downloadPercent.setVisibility(View.VISIBLE); holder.statusIcon.setProgress(appContent.getDownloadPercent()); holder.downloadPercent.setText("下載進(jìn)度:" + appContent.getDownloadPercent() + "%"); } } /** * 局部刷新 * @param view * @param itemIndex */ public void updateView(View view, int itemIndex) { if(view == null) { return; } //從view中取得holder ViewHolder holder = (ViewHolder) view.getTag(); holder.statusIcon = (DownloadPercentView) view.findViewById(R.id.status_icon); holder.name = (TextView) view.findViewById(R.id.name); holder.downloadPercent = (TextView) view.findViewById(R.id.download_percent); holder.progressBar = (ProgressBar) view.findViewById(R.id.progressbar); setData(holder, itemIndex); } /** * 根據(jù)狀態(tài)設(shè)置圖標(biāo) * @param downloadPercentView * @param status */ private void setIconByStatus(DownloadPercentView downloadPercentView, AppContent.Status status) { downloadPercentView.setVisibility(View.VISIBLE); if(status == AppContent.Status.PENDING) { downloadPercentView.setStatus(DownloadPercentView.STATUS_PEDDING); } if(status == AppContent.Status.DOWNLOADING) { downloadPercentView.setStatus(DownloadPercentView.STATUS_DOWNLOADING); } if(status == AppContent.Status.WAITING) { downloadPercentView.setStatus(DownloadPercentView.STATUS_WAITING); } if(status == AppContent.Status.PAUSED) { downloadPercentView.setStatus(DownloadPercentView.STATUS_PAUSED); } if(status == AppContent.Status.FINISHED) { downloadPercentView.setStatus(DownloadPercentView.STATUS_FINISHED); } } private class ViewHolder { private DownloadPercentView statusIcon; private TextView name; private TextView downloadPercent; private ProgressBar progressBar; } }
其實(shí)這些代碼就是我上篇博文《AsyncTask實(shí)現(xiàn)多任務(wù)多線程下載》的例子中的,如果需要可以去下載。
以上內(nèi)容是關(guān)于Android開發(fā)之ListView實(shí)現(xiàn)Item局部刷新的全部內(nèi)容,希望對大家有用,更多有關(guān)listview局部刷新問題,請登錄腳本之家官網(wǎng)查詢,謝謝!
- android的ListView點(diǎn)擊item使item展開的做法的實(shí)現(xiàn)代碼
- Android編程實(shí)現(xiàn)Listview點(diǎn)擊展開和隱藏的方法
- Android編程實(shí)現(xiàn)ListView中item部分區(qū)域添加點(diǎn)擊事件功能
- Android開發(fā)實(shí)現(xiàn)ListView點(diǎn)擊item改變顏色功能示例
- Android 實(shí)現(xiàn)ListView的點(diǎn)擊變色的實(shí)例
- Android ListView的Item點(diǎn)擊效果的定制
- Android實(shí)現(xiàn)為ListView同時(shí)設(shè)置點(diǎn)擊時(shí)的背景和點(diǎn)擊松手之后的背景
- Android ListView的item背景色設(shè)置和item點(diǎn)擊無響應(yīng)的解決方法
- android ListView內(nèi)數(shù)據(jù)的動(dòng)態(tài)添加與刪除實(shí)例代碼
- android ListView和GridView拖拽移位實(shí)現(xiàn)代碼
- Android開發(fā)實(shí)現(xiàn)ListView點(diǎn)擊展開收起效果示例
相關(guān)文章
分別用ToolBar和自定義導(dǎo)航欄實(shí)現(xiàn)沉浸式狀態(tài)欄
本文主要介紹了分別用ToolBar和自定義導(dǎo)航欄實(shí)現(xiàn)沉浸式狀態(tài)欄的方法步驟,具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01Android 代碼一鍵實(shí)現(xiàn)銀行卡綁定功能
這篇文章主要介紹了Android 代碼一鍵實(shí)現(xiàn)銀行卡綁定功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Android自定義控件實(shí)現(xiàn)帶文字提示的SeekBar
這篇文章主要給大家介紹了關(guān)于Android自定義控件實(shí)現(xiàn)帶文字提示的SeekBar的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12Android實(shí)現(xiàn)計(jì)時(shí)與倒計(jì)時(shí)的方法匯總
這篇文章主要介紹了Android實(shí)現(xiàn)計(jì)時(shí)與倒計(jì)時(shí)的方法匯總,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06Android View進(jìn)行手勢識(shí)別詳解
本文主要介紹 Android View進(jìn)行手勢識(shí)別,這里整理了相關(guān)資料和簡單示例,有興趣的小伙伴可以參考下2016-08-08Android實(shí)現(xiàn)快速滾動(dòng)FastScrollView效果
這篇文章主要介紹了Android實(shí)現(xiàn)快速滾動(dòng)FastScrollView效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08為Retrofit統(tǒng)一添加post請求的默認(rèn)參數(shù)的方法
這篇文章主要介紹了為Retrofit統(tǒng)一添加post請求的默認(rèn)參數(shù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04Android浮動(dòng)窗口實(shí)現(xiàn)原理及代碼實(shí)例
這篇文章主要介紹了Android浮動(dòng)窗口實(shí)現(xiàn)原理及代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Android 實(shí)現(xiàn)圖片轉(zhuǎn)二進(jìn)制流及二進(jìn)制轉(zhuǎn)字符串
這篇文章主要介紹了Android 實(shí)現(xiàn)圖片轉(zhuǎn)二進(jìn)制流及二進(jìn)制轉(zhuǎn)字符串,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03