对于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 }
详细示例参考:https://github.com/liuling07/MultiTaskAndThreadDownload