Android开发之ListView实现Item局部刷新
对于android中的ListView刷新机制,大多数的程序员都是很熟悉的,修改或者添加adapter中的数据源之后,然后调用notifyDataSetChanged()刷新ListView。在这种模式下,我们会在getView中,根据不同的数据源,让控件显示不同的内容。这种模式是最常见的刷新模式,当我们来回滑动ListView的时候,调用adapter的getView方法,然后listview对adapter返回的View进行绘制。这种模式下,View的显示内容或状态都记录在adapter里面的数据源中,listview的更新频率不频繁,它随着数据源的变化而更新。
但是毛票票小编在做公司项目的时候,有个下载模块,因为可能同时下载好几个数据,所以用的listview展示所有正在下载的内容。因为下载进度要实时更新,所以要不停的调用notifyDateSetChanged刷新数据。这样会不停的重新绘制整个listview的界面,性能开销非常大。而且如果每个item有图片的话,每个item的图片都需要重新加载,就算图片做了内存缓存,刷新一下图片也会闪一下,不停的刷新就会导致各个item的图片不停的闪,体验一点都不好。
那么对于上面问题,有没有解决办法呢?当然是有的。我们可以针对某一个item进行局部更新,而不影响其它没有修改的item。那么具体如何实现的呢?我们看下面的代码。
privatevoidupdateView(intitemIndex){
//得到第一个可显示控件的位置,
intvisiblePosition=mListView.getFirstVisiblePosition();
//只有当要更新的view在可见的位置时才更新,不可见时,跳过不更新
if(itemIndex-visiblePosition>=){
//得到要更新的item的view
Viewview=mListView.getChildAt(itemIndex-visiblePosition);
//调用adapter更新界面
mAdapter.updateView(view,itemIndex);
}
}
这个函数主要是根据传入的itemIndex来获取第itemIndex的数据所显示的view。itemIndex就是要修改的数据再List集合中的位置,比如我这里下载进度有更新,发了一个广播这里接收到了,需要修改该下载内容的进度条,广播接收器可以这么写:
@Override
publicvoidonReceive(Contextcontext,Intentintent){
AppContentappContent=intent.getParcelableExtra("appContent");
if(appContent==null)return;
intitemIndex=;
for(AppContentappContent:mList){
if(appContent.getUrl().equals(appContent.getUrl())){
itemIndex=mList.indexOf(appContent);
appContent.setDownloadPercent(appContent.getDownloadPercent());
break;
}
}
updateView(itemIndex);
}
下面看Adapter的具体代码:
publicclassAppContentAdapterextendsBaseAdapter{
privateList<AppContent>mDates=null;
privateContextmContext;
publicAppContentAdapter(Contextcontext){
this.mContext=context;
}
@Override
publicintgetCount(){
returnmDates.size();
}
@Override
publicObjectgetItem(intposition){
returnmDates.get(position);
}
@Override
publiclonggetItemId(intposition){
returnposition;
}
publicvoidsetDates(List<AppContent>mDates){
this.mDates=mDates;
}
@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
ViewHolderholder=null;
if(convertView==null){
holder=newViewHolder();
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);
returnconvertView;
}
/**
*设置viewHolder的数据
*@paramholder
*@paramitemIndex
*/
privatevoidsetData(ViewHolderholder,intitemIndex){
AppContentappContent=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()+"%");
}
}
/**
*局部刷新
*@paramview
*@paramitemIndex
*/
publicvoidupdateView(Viewview,intitemIndex){
if(view==null){
return;
}
//从view中取得holder
ViewHolderholder=(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);
}
/**
*根据状态设置图标
*@paramdownloadPercentView
*@paramstatus
*/
privatevoidsetIconByStatus(DownloadPercentViewdownloadPercentView,AppContent.Statusstatus){
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);
}
}
privateclassViewHolder{
privateDownloadPercentViewstatusIcon;
privateTextViewname;
privateTextViewdownloadPercent;
privateProgressBarprogressBar;
}
}
其实这些代码就是我上篇博文《AsyncTask实现多任务多线程下载》的例子中的,如果需要可以去下载。
以上内容是关于Android开发之ListView实现Item局部刷新的全部内容,希望对大家有用,更多有关listview局部刷新问题,请登录毛票票官网查询,谢谢!