編輯:關於Android編程
對於android中的ListView刷新機制,大多數的程序員都是很熟悉的,修改或者添加adapter中的數據源之後,然後調用notifyDataSetChanged()刷新ListView。在這種模式下,我們會在getView中,根據不同的數據源,讓控件顯示不同的內容。這種模式是最常見的刷新模式,當我們來回滑動ListView的時候,調用adapter的getView方法,然後listview對adapter返回的View進行繪制。這種模式下,View的顯示內容或狀態都記錄在adapter裡面的數據源中,listview的更新頻率不頻繁,它隨著數據源的變化而更新。
但是本站小編在做公司項目的時候,有個下載模塊,因為可能同時下載好幾個數據,所以用的listview展示所有正在下載的內容。因為下載進度要實時更新,所以要不停的調用notifyDateSetChanged刷新數據。這樣會不停的重新繪制整個listview的界面,性能開銷非常大。而且如果每個item有圖片的話,每個item的圖片都需要重新加載,就算圖片做了內存緩存,刷新一下圖片也會閃一下,不停的刷新就會導致各個item的圖片不停的閃,體驗一點都不好。
那麼對於上面問題,有沒有解決辦法呢?當然是有的。我們可以針對某一個item進行局部更新,而不影響其它沒有修改的item。那麼具體如何實現的呢?我們看下面的代碼。
private void updateView(int itemIndex) {
//得到第一個可顯示控件的位置,
int visiblePosition = mListView.getFirstVisiblePosition();
//只有當要更新的view在可見的位置時才更新,不可見時,跳過不更新
if (itemIndex - visiblePosition >= ) {
//得到要更新的item的view
View view = mListView.getChildAt(itemIndex - visiblePosition);
//調用adapter更新界面
mAdapter.updateView(view, itemIndex);
}
}
這個函數主要是根據傳入的itemIndex來獲取第itemIndex的數據所顯示的view。itemIndex就是要修改的數據再List集合中的位置,比如我這裡下載進度有更新,發了一個廣播這裡接收到了,需要修改該下載內容的進度條,廣播接收器可以這麼寫:
@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;
}
/**
* 設置viewHolder的數據
* @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("下載進度:" + 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);
}
/**
* 根據狀態設置圖標
* @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;
}
}
以上內容是關於Android開發之ListView實現Item局部刷新的全部內容,希望對大家有用,更多有關listview局部刷新問題,請登錄本站官網查詢,謝謝!
Android 源碼系列之(二)從安全的角度深入理解BroadcastReceiver(上)
提起BroadcastReceiver大家都很熟悉,它和Activity,Service以及ContentProvider並稱為Android的四大組件(四大金剛),可見
手把手教你解析Resources.arsc
一、前言對於APK裡面的Resources.arsc文件大家應該都知道是干什麼的,它實際上就是App的資源索引表。下面我會結合實例對它的格式做一下剖析,讀完這篇文章應該能
Android中通過ActionBar為標題欄添加搜索及分享視窗
在Android3.0之後,Google對UI導航設計上進行了一系列的改革,其中有一個非常好用的新功能就是引入的ActionBar,他用於取代3.0之前的標題欄,並提供更
Android加殼原理分析
0x00閱讀本文前,建議讀者首先閱讀Android加殼原理,參考文章Android中的Apk的加固(加殼)原理解析和實現。如果沒有看過這篇文章,本文理解起來比較困難。0x
Android Multimedia框架總結(十九)Camera2框架C/S模型之CameraService啟動及與Client連接過程
Agenda:一張圖看Camera2框架類圖 CameraService