ListView實現Item局部刷新


   對於ListView數據的刷新大家都知道,改變Adapter的數據源,然后調用Adapter的notifyDateSetChanged()方法即可。

  但是博主在做公司項目的時候,有個下載模塊,因為可能同時下載好幾個數據,所以用的listview展示所有正在下載的內容。因為下載進度要實時更新,所以要不停的調用notifyDateSetChanged刷新數據。這樣會不停的重新繪制整個listview的界面,性能開銷非常大。而且如果每個item有圖片的話,每個item的圖片都需要重新加載,就算圖片做了內存緩存,刷新一下圖片也會閃一下,不停的刷新就會導致各個item的圖片不停的閃,體驗一點都不好。

  那么對於上面問題,有沒有解決辦法呢?當然是有的。我們可以針對某一個item進行局部更新,而不影響其它沒有修改的item。那么具體如何實現的呢?我們看下面的代碼。

 1     private void updateView(int itemIndex) {
 2         //得到第一個可顯示控件的位置,
 3         int visiblePosition = mListView.getFirstVisiblePosition();
 4         //只有當要更新的view在可見的位置時才更新,不可見時,跳過不更新
 5         if (itemIndex - visiblePosition >= 0) {
 6             //得到要更新的item的view
 7             View view = mListView.getChildAt(itemIndex - visiblePosition);
 8             //調用adapter更新界面
 9             mAdapter.updateView(view, itemIndex);
10         }
11     }

  這個函數主要是根據傳入的itemIndex來獲取第itemIndex的數據所顯示的view。itemIndex就是要修改的數據再List集合中的位置,比如我這里下載進度有更新,發了一個廣播這里接收到了,需要修改該下載內容的進度條,廣播接收器可以這么寫:

 1         @Override
 2         public void onReceive(Context context, Intent intent) {
 3             AppContent appContent = intent.getParcelableExtra("appContent");
 4             if(appContent == null) return;
 5             int itemIndex = 0;
 6             for(AppContent appContent1 : mList) {
 7                 if(appContent.getUrl().equals(appContent1.getUrl())) {
 8                     itemIndex = mList.indexOf(appContent1);
 9                     appContent1.setDownloadPercent(appContent.getDownloadPercent());
10                     break;
11                 }
12             }
13             updateView(itemIndex);
14         }

  下面看Adapter的具體代碼:

  1 public class AppContentAdapter extends BaseAdapter{
  2 
  3     private List<AppContent> mDates = null;
  4     private Context mContext;
  5 
  6     public AppContentAdapter(Context context) {
  7         this.mContext = context;
  8     }
  9 
 10     @Override
 11     public int getCount() {
 12         return mDates.size();
 13     }
 14 
 15     @Override
 16     public Object getItem(int position) {
 17         return mDates.get(position);
 18     }
 19 
 20     @Override
 21     public long getItemId(int position) {
 22         return position;
 23     }
 24 
 25     public void setDates(List<AppContent> mDates) {
 26         this.mDates = mDates;
 27     }
 28 
 29     @Override
 30     public View getView(int position, View convertView, ViewGroup parent) {
 31         ViewHolder holder = null;
 32         if (convertView == null) {
 33             holder = new ViewHolder();
 34             convertView = LayoutInflater.from(mContext).inflate(
 35                     R.layout.listitem_download, null);
 36             holder.statusIcon = (DownloadPercentView) convertView.findViewById(R.id.status_icon);
 37             holder.name = (TextView) convertView.findViewById(R.id.name);
 38             holder.downloadPercent = (TextView) convertView.findViewById(R.id.download_percent);
 39             holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progressbar);
 40             convertView.setTag(holder);
 41         } else {
 42             holder = (ViewHolder) convertView.getTag();
 43         }
 44         setData(holder, position);
 45         return convertView;
 46     }
 47 
 48     /**
 49      * 設置viewHolder的數據
 50      * @param holder
 51      * @param itemIndex
 52      */
 53     private void setData(ViewHolder holder, int itemIndex) {
 54         AppContent appContent = mDates.get(itemIndex);
 55         holder.name.setText(appContent.getName());
 56         holder.progressBar.setProgress(appContent.getDownloadPercent());
 57         setIconByStatus(holder.statusIcon, appContent.getStatus());
 58         if(appContent.getStatus() == AppContent.Status.PENDING) {
 59             holder.downloadPercent.setVisibility(View.INVISIBLE);
 60         } else {
 61             holder.downloadPercent.setVisibility(View.VISIBLE);
 62             holder.statusIcon.setProgress(appContent.getDownloadPercent());
 63             holder.downloadPercent.setText("下載進度:" + appContent.getDownloadPercent() + "%");
 64         }
 65     }
 66 
 67 
 68     /**
 69      * 局部刷新
 70      * @param view
 71      * @param itemIndex
 72      */
 73     public void updateView(View view, int itemIndex) {
 74         if(view == null) {
 75             return;
 76         }
 77         //從view中取得holder
 78         ViewHolder holder = (ViewHolder) view.getTag();
 79         holder.statusIcon = (DownloadPercentView) view.findViewById(R.id.status_icon);
 80         holder.name = (TextView) view.findViewById(R.id.name);
 81         holder.downloadPercent = (TextView) view.findViewById(R.id.download_percent);
 82         holder.progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
 83         setData(holder, itemIndex);
 84     }
 85 
 86     /**
 87      * 根據狀態設置圖標
 88      * @param downloadPercentView
 89      * @param status
 90      */
 91     private void setIconByStatus(DownloadPercentView downloadPercentView, AppContent.Status status) {
 92         downloadPercentView.setVisibility(View.VISIBLE);
 93         if(status == AppContent.Status.PENDING) {
 94             downloadPercentView.setStatus(DownloadPercentView.STATUS_PEDDING);
 95         }
 96         if(status == AppContent.Status.DOWNLOADING) {
 97             downloadPercentView.setStatus(DownloadPercentView.STATUS_DOWNLOADING);
 98         }
 99         if(status == AppContent.Status.WAITING) {
100             downloadPercentView.setStatus(DownloadPercentView.STATUS_WAITING);
101         }
102         if(status == AppContent.Status.PAUSED) {
103             downloadPercentView.setStatus(DownloadPercentView.STATUS_PAUSED);
104         }
105         if(status == AppContent.Status.FINISHED) {
106             downloadPercentView.setStatus(DownloadPercentView.STATUS_FINISHED);
107         }
108     }
109 
110     private class ViewHolder {
111         private DownloadPercentView statusIcon;
112         private TextView name;
113         private TextView downloadPercent;
114         private ProgressBar progressBar;
115     }
116 }

  其實這些代碼就是我上篇博文《AsyncTask實現多任務多線程下載》的例子中的,如果需要可以去下載。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM