ListView实现Item局部刷新
2015-10-20 21:44
281 查看
对于ListView数据的刷新大家都知道,改变Adapter的数据源,然后调用Adapter的notifyDateSetChanged()方法即可。
但是博主在做公司项目的时候,有个下载模块,因为可能同时下载好几个数据,所以用的listview展示所有正在下载的内容。因为下载进度要实时更新,所以要不停的调用notifyDateSetChanged刷新数据。这样会不停的重新绘制整个listview的界面,性能开销非常大。而且如果每个item有图片的话,每个item的图片都需要重新加载,就算图片做了内存缓存,刷新一下图片也会闪一下,不停的刷新就会导致各个item的图片不停的闪,体验一点都不好。
那么对于上面问题,有没有解决办法呢?当然是有的。我们可以针对某一个item进行局部更新,而不影响其它没有修改的item。那么具体如何实现的呢?我们看下面的代码。
这个函数主要是根据传入的itemIndex来获取第itemIndex的数据所显示的view。itemIndex就是要修改的数据再List集合中的位置,比如我这里下载进度有更新,发了一个广播这里接收到了,需要修改该下载内容的进度条,广播接收器可以这么写:
下面看Adapter的具体代码:
其实这些代码就是我上篇博文《AsyncTask实现多任务多线程下载》的例子中的,如果需要可以去下载。
但是博主在做公司项目的时候,有个下载模块,因为可能同时下载好几个数据,所以用的listview展示所有正在下载的内容。因为下载进度要实时更新,所以要不停的调用notifyDateSetChanged刷新数据。这样会不停的重新绘制整个listview的界面,性能开销非常大。而且如果每个item有图片的话,每个item的图片都需要重新加载,就算图片做了内存缓存,刷新一下图片也会闪一下,不停的刷新就会导致各个item的图片不停的闪,体验一点都不好。
那么对于上面问题,有没有解决办法呢?当然是有的。我们可以针对某一个item进行局部更新,而不影响其它没有修改的item。那么具体如何实现的呢?我们看下面的代码。
private void updateView(int itemIndex) { //得到第一个可显示控件的位置, int visiblePosition = mListView.getFirstVisiblePosition(); //只有当要更新的view在可见的位置时才更新,不可见时,跳过不更新 if (itemIndex - visiblePosition >= 0) { //得到要更新的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 = 0; for(AppContent appContent1 : mList) { if(appContent.getUrl().equals(appContent1.getUrl())) { itemIndex = mList.indexOf(appContent1); appContent1.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; } }
其实这些代码就是我上篇博文《AsyncTask实现多任务多线程下载》的例子中的,如果需要可以去下载。
相关文章推荐
- UNITY 5.2 Resources类
- Unix系统的信号机制最简单的接口—signal函数
- hdu3466Proud Merchants【至少需要Qi才能买Pi】
- python画图2
- 在浏览器里输入网址到显示完整网页
- Windows系统下C++ Socket UDP编程
- Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
- iOS设计模式 - 组合
- Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
- 利用sublime的snippet功能快速创建代码段
- Windows系统下C++socket TCP编程步骤
- JSP的9大内置对象及4个作用域
- mysql与oracle转换遇到的不同--case when
- iOS UILabel 文字自动左上角对齐
- 在openstack环境中安装rackspace private cloud --1 环境准备
- hp-unix LVM管理
- POJ 3126 Prime Path(筛法,双向搜索)
- Entity Framework学习六:一些常用查询技术
- 做项目中没经验遇到的各种问题
- JAVA通过JNI调用本地C语言方法