【android】ListView的局部刷新

1.简介

对于android中的ListView刷新机制,大多数的程序员都是很熟悉的,修改或者添加adapter中的数据源之后,然后调用notifyDataSetChanged()刷新ListView。在这种模式下,我们会在getView中,根据不同的数据源,让控件显示不同的内容。这种模式是最常见的刷新模式,当我们来回滑动ListView的时候,调用adapter的getView方法,然后listview对adapter返回的View进行绘制。这种模式下,View的显示内容或状态都记录在adapter里面的数据源中,listview的更新频率不频繁,它随着数据源的变化而更新。

->ListView局部刷新问题的引入:

假设我们的ListView的Item中有一个进度条(ProgressBar)和一个按钮,当我们点击一下按钮,进度条就会从0到100进行刷新,而且一般都需要在1s以内完成刷新过程,也就是说:在ListView的任一个Item中,触发了Button的事件之后,在1s以内,或者更短的时间,ProgressBar需要刷新100次。显然,如果我们使用修改数据源,调用notifyDataSetChanged()进行刷新的机制明显是不恰当的,效率极低,而且不一定凑效。那么,我们自然想到当点击的时候,希望能够获取到点击后的View内部的ProgressBar控件的对象,然后直接调用progressBar的setProgress就可以了,本以为这样就大功告成了。忽然,你会发现,当progressBar正在更新的时候,此时,往下滑listview,突然发现下面的某个进度条也在更新。仔细一分析,还真有道理,因为ListView中的View是复用的,当你向下滑动listview的时候,你此时操作的progressBar对象,已经不是刚才点击的那个Item了,因为很多Item复用一个View。那么如何解决这个问题呢?

2.解决方案

记录点击的Item的position,然后在更新过程中,不断的判断,该position是不是介于可见的Item之间,如果是,则更新,否者,不更新。

[java]  view plain copy
  1. private void updateProgressPartly(int progress,int position){  
  2.         int firstVisiblePosition = listview.getFirstVisiblePosition();  
  3.         int lastVisiblePosition = listview.getLastVisiblePosition();  
  4.         if(position>=firstVisiblePosition && position<=lastVisiblePosition){  
  5.             View view = listview.getChildAt(position - firstVisiblePosition);  
  6.             if(view.getTag() instanceof ViewHolder){  
  7.                 ViewHolder vh = (ViewHolder)view.getTag();  
  8.                 vh.pb.setProgress(progress);  
  9.             }  
  10.         }  
  11.     }  


其他相关代码:

ListAdapter

[java]  view plain copy
  1. /* 
  2.  * $filename: ListAdapter.java,v $ 
  3.  * $Date: 2014-9-19  $ 
  4.  * Copyright (C) ZhengHaibo, Inc. All rights reserved. 
  5.  * This software is Made by Zhenghaibo. 
  6.  */  
  7. package net.mobctrl.listviewdemo;  
  8.   
  9. import java.util.ArrayList;  
  10. import java.util.List;  
  11.   
  12. import android.content.Context;  
  13. import android.view.LayoutInflater;  
  14. import android.view.View;  
  15. import android.view.View.OnClickListener;  
  16. import android.view.ViewGroup;  
  17. import android.widget.BaseAdapter;  
  18. import android.widget.Button;  
  19. import android.widget.ProgressBar;  
  20.   
  21. /* 
  22.  *@author: ZhengHaibo   
  23.  *blog:     http://blog.csdn.net/nuptboyzhb 
  24.  *mail:    [email protected] 
  25.  *web:     http://www.mobctrl.net 
  26.  *2014-9-19  Nanjing,njupt,China 
  27.  */  
  28. public class ListAdapter extends BaseAdapter {  
  29.   
  30.     private List<Model> datas;  
  31.     private Context context;  
  32.       
  33.     private UpdateCallback updateCallback;  
  34.       
  35.     public UpdateCallback getUpdateCallback() {  
  36.         return updateCallback;  
  37.     }  
  38.   
  39.     public void setUpdateCallback(UpdateCallback updateCallback) {  
  40.         this.updateCallback = updateCallback;  
  41.     }  
  42.   
  43.     public ListAdapter(Context context) {  
  44.         datas = new ArrayList<Model>();  
  45.         this.context = context;  
  46.     }  
  47.   
  48.     public void addData(Model model) {  
  49.         datas.add(model);  
  50.         notifyDataSetChanged();  
  51.     }  
  52.   
  53.     @Override  
  54.     public int getCount() {  
  55.         // TODO Auto-generated method stub  
  56.         return datas.size();  
  57.     }  
  58.   
  59.     @Override  
  60.     public Object getItem(int pos) {  
  61.         // TODO Auto-generated method stub  
  62.         return datas.get(pos);  
  63.     }  
  64.   
  65.     @Override  
  66.     public long getItemId(int arg0) {  
  67.         // TODO Auto-generated method stub  
  68.         return 0;  
  69.     }  
  70.   
  71.     @Override  
  72.     public View getView(final int pos, View convertView, ViewGroup viewGroup) {  
  73.         final Model model = datas.get(pos);  
  74.         ViewHolder viewHolder = null;  
  75.         if (null == convertView) {  
  76.             viewHolder = new ViewHolder();  
  77.             convertView = LayoutInflater.from(context).inflate(  
  78.                     R.layout.list_item_layout, null);  
  79.             viewHolder.pb = (ProgressBar) convertView  
  80.                     .findViewById(R.id.pb_show);  
  81.             viewHolder.btn = (Button) convertView.findViewById(R.id.btn);  
  82.             convertView.setTag(viewHolder);  
  83.         } else {  
  84.             viewHolder = (ViewHolder) convertView.getTag();  
  85.             convertView.setTag(viewHolder);  
  86.         }  
  87.         viewHolder.btn.setText(model.getName());  
  88.         viewHolder.btn.setOnClickListener(new OnClickListener() {  
  89.             @Override  
  90.             public void onClick(View v) {  
  91.                 if(null != updateCallback){  
  92.                     updateCallback.startProgress(model,pos);  
  93.                 }  
  94.             }  
  95.         });  
  96.         viewHolder.pb.setProgress(0);  
  97.         // cache the view  
  98.         return convertView;  
  99.     }  
  100.       
  101.     public static class ViewHolder {  
  102.         ProgressBar pb;  
  103.         Button btn;  
  104.     }  
  105.   
  106. }  

Activity

[java]  view plain copy
  1. package net.mobctrl.listviewdemo;  
  2.   
  3. import net.mobctrl.listviewdemo.ListAdapter.ViewHolder;  
  4.   
  5. import org.androidannotations.annotations.AfterViews;  
  6. import org.androidannotations.annotations.EActivity;  
  7. import org.androidannotations.annotations.UiThread;  
  8. import org.androidannotations.annotations.ViewById;  
  9.   
  10. import android.app.Activity;  
  11. import android.view.View;  
  12. import android.widget.ListView;  
  13. /** 
  14.  * @author 郑海波 
  15.  * @webset http://www.mobctrl.net 
  16.  * ListView的局部刷新 
  17.  */  
  18. @EActivity(R.layout.activity_main)  
  19. public class MainActivity extends Activity implements UpdateCallback{  
  20.   
  21.     @ViewById  
  22.     ListView listview;  
  23.       
  24.     private ListAdapter adapter;  
  25.       
  26.     @AfterViews  
  27.     void afterViews() {  
  28.         adapter = new ListAdapter(this);  
  29.         adapter.setUpdateCallback(this);  
  30.         listview.setAdapter(adapter);  
  31.         initDatas();  
  32.     }  
  33.   
  34.     private void initDatas() {  
  35.         for(int i = 0;i<100;i++){  
  36.             Model model = new Model(i, "<Click> --> ");  
  37.             adapter.addData(model);  
  38.         }  
  39.     }  
  40.   
  41.     @Override  
  42.     public void startProgress(final Model model,final int position) {  
  43.         /** start the Thread to update the Progress*/  
  44.         new Thread(new Runnable() {  
  45.               
  46.             @Override  
  47.             public void run() {  
  48.                 for(int i = 0;i<=100;i++){  
  49.                     updateProgressInUiThread(model, i,position);  
  50.                     try {  
  51.                         Thread.sleep(50);  
  52.                     } catch (InterruptedException e) {  
  53.                         // TODO Auto-generated catch block  
  54.                         e.printStackTrace();  
  55.                     }  
  56.                 }  
  57.             }  
  58.         }).start();  
  59.     }  
  60.       
  61.     @UiThread  
  62.     void updateProgressInUiThread(Model model,int progress,int position){  
  63.         updateProgressPartly(progress,position);  
  64.     }  
  65.       
  66.       
  67.     private void updateProgressPartly(int progress,int position){  
  68.         int firstVisiblePosition = listview.getFirstVisiblePosition();  
  69.         int lastVisiblePosition = listview.getLastVisiblePosition();  
  70.         if(position>=firstVisiblePosition && position<=lastVisiblePosition){  
  71.             View view = listview.getChildAt(position - firstVisiblePosition);  
  72.             if(view.getTag() instanceof ViewHolder){  
  73.                 ViewHolder vh = (ViewHolder)view.getTag();  
  74.                 vh.pb.setProgress(progress);  
  75.             }  
  76.         }  
  77.     }  
  78.       
  79. }  


布局:

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.     <Button  
  6.         android:id="@+id/btn"  
  7.         android:layout_width="wrap_content"  
  8.         android:layout_height="40dp"  
  9.         android:layout_alignParentLeft="true"  
  10.         android:layout_centerVertical="true"  
  11.         android:gravity="center"  
  12.         android:text="test" />  
  13.     <ProgressBar  
  14.         android:id="@+id/pb_show"  
  15.         style="@android:style/Widget.Holo.ProgressBar.Horizontal"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="40dp"  
  18.         android:layout_alignParentRight="true"  
  19.         android:layout_centerVertical="true"  
  20.         android:layout_marginLeft="10dp"  
  21.         android:layout_marginRight="10dp"  
  22.         android:layout_toRightOf="@id/btn"  
  23.         android:background="@android:color/background_light"  
  24.         android:max="100"  
  25.         android:progress="0" />  
  26. </RelativeLayout>  

整个项目的源代码: https://github.com/nuptboyzhb/ListViewPartRefreash

效果为:

【android】ListView的局部刷新_第1张图片

无论如何上下滑动ListView,都能够正常刷新



未经允许不得用于商业目的

欢迎加入QQ群讨论:android开发联盟: 272209595



转自:http://blog.csdn.net/nupt123456789/article/details/39432781

你可能感兴趣的:(android,ListView)