安卓lisView优化(2)

来源:互联网 发布:类似丫丫云播的软件 编辑:程序博客网 时间:2024/06/02 04:15

接着上篇点击,我们使用了ListView 的缓存视图方法去节省加载时间,那么今天我们使用视图缓存+ViewHolder的方法来优化ListView

  (1)什么是ViewHolder?   

        我们在使用ViewHolder之前我们先理清楚它的概念,从字面意思来理解它的意思是“视图持有者”,我们可以知道他是跟View有关的一个概念,从google文档的官方定义知道他是一个静态类,一般只有属性没有方法,它的作用就是一个临时存储器,存储视图的一些属性,那么他在ListView中有什么作用呢?

      我们知道ListView在加载列表时候它需要的东西无非就是:列表长度、每一项的列表View,当前项的位置;有了这3个东西我们就能产生一个ListView列表,这个可以从适配器中获得,其中长度其实就是你得到数据的长度,而当前项的位置则由当前加载位置决定的,因此ListView的加载时间和内存消耗主要是在:View的产生上面,而View的优化我们可以从2个方面进行:

    a.View的创建时间的优化,因此尽量的重复利用已经创建好的View

    b.查找View上面控件的优化,一次尽可能的减少findViewById()的使用

 前者我们可以通过convertView==null的判断来减少重复创建View的时间,后者则可以使用静态ViewHolder来减少findViewById()的使用

 (2)实例比较研究

 我们来动手创建一个来试试:

首先我们来自定义一个Adapter,用来作为ListView的适配器:

   

[java] view plain copy
  1. public class ListViewAdapterBas extends BaseAdapter{  
  2.     private Context context;  
  3.     private List<Map<String,Object>> data;  
  4.     /**  
  5.      * @param context  上下文 
  6.      * @param data  你要加载到ListView上面的数据 
  7.      */  
  8.     public ListViewAdapterBas(Context context){  
  9.          List<Map<String,Object>> itemList=new ArrayList<Map<String,Object>>();  
  10.             Map<String,Object> mMap=null;  
  11.             for(int i=0;i<10000;i++){  
  12.                 mMap=new HashMap<String,Object>();  
  13.                 mMap.put("image", R.drawable.two);  
  14.                 mMap.put("title""美女:aspen");  
  15.                 itemList.add(mMap);  
  16.             }  
  17.         this.context=context;  
  18.         this.data=itemList;  
  19.     }  
  20.       
  21.     static class ViewHolder{  
  22.         //此处就是你定义的中包含的 控件 Item  
  23.         ImageView image;  
  24.         TextView text;  
  25.     }  
  26.       
  27.     @Override  
  28.     public int getCount() {  
  29.         //这里就是返回ListView的总长度  
  30.         return data.size();  
  31.     }  
  32.   
  33.     @Override  
  34.     public Object getItem(int arg0) {  
  35.         // TODO Auto-generated method stub  
  36.         return arg0;//得到当前加载的项  
  37.     }  
  38.   
  39.     @Override  
  40.     public long getItemId(int arg0) {  
  41.         // TODO Auto-generated method stub  
  42.         return arg0;  
  43.     }  
  44.   
  45.     @Override  
  46.     public View getView(int position, View convertView, ViewGroup parent) {  
  47.         long startTime = System.nanoTime();  
  48.         ViewHolder holder;  
  49.         LayoutInflater mInflater=LayoutInflater.from(context);  
  50.         //判断是否已经加载过视图了,如果加载过的话就直接使用,如果没有加载的话就重新加载  
  51.         if(convertView==null){  
  52.             convertView = mInflater.inflate(R.layout.listview_item, null);  
  53.             holder = new ViewHolder();  
  54.             holder.image=(ImageView)convertView.findViewById(R.id.image);  
  55.             holder.text=(TextView)convertView.findViewById(R.id.title);  
  56.         }else{  
  57.             holder = (ViewHolder)convertView.getTag();  
  58.         }  
  59.           
  60.         holder.image.setImageResource(Integer.parseInt(data.get(position).get("image").toString()));  
  61.         holder.text.setText(data.get(position).get("title").toString());  
  62.         // 停止计时  
  63.         long endTime = System.nanoTime();  
  64.         // 计算耗时  
  65.         long val = (endTime - startTime) / 1000L;  
  66.         //Log.e("Test", "Position:" + position + ":" + val);  
  67.         return convertView;  
  68.     }  
  69.   
  70. }  
代码分析:viewHolder

[java] view plain copy
  1. static class ViewHolder{  
  2.         //此处就是你定义的中包含的 控件 Item  
  3.         ImageView image;  
  4.         TextView text;  
  5.     }  
定义了一个ViewHolder,这里面就是我们列表Item的对应控件,一个图片和一个标题,注意是静态的,静态的好处就是节省了实例化所花费的时间,调用速度回更快,不过占用的内存可能会更多。

getView代码

[java] view plain copy
  1. if(convertView==null){  
  2.             convertView = mInflater.inflate(R.layout.listview_item, null);  
  3.             holder = new ViewHolder();  
  4.             holder.image=(ImageView)convertView.findViewById(R.id.image);  
  5.             holder.text=(TextView)convertView.findViewById(R.id.title);  
  6.         }else{  
  7.             holder = (ViewHolder)convertView.getTag();  
  8.         }  
判断当前的视图是否已经创建,如果创建了就直接加载,就直接使用getTag()来获取视图,另外使用holder避免了重复加载。

最后直接在Activity中引用:

 

[java] view plain copy
  1. public class MainActivity extends Activity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         ListView lv=(ListView)findViewById(R.id.listView1);  
  8.         long startTime = System.nanoTime();  
  9.         ListViewAdapterBas listViewAd=new ListViewAdapterBas(this);  
  10.         lv.setAdapter(listViewAd) ;   
  11.         //ListViewAdapter.setListViewAdpter(this, lv);  
  12.         // 停止计时  
  13.         long endTime = System.nanoTime();  
  14.         // 计算耗时  
  15.         long val = (endTime - startTime) / 1000L;  
  16.         Log.e("总耗时:""Position:" + val);  
  17.           
  18.           
  19.     }  
  20.   
  21.       
  22.     @Override  
  23.     public boolean onCreateOptionsMenu(Menu menu) {  
  24.         // Inflate the menu; this adds items to the action bar if it is present.  
  25.         getMenuInflater().inflate(R.menu.main, menu);  
  26.         return true;  
  27.     }  
  28.   
  29. }  
我们来看看和前一篇文章对比消耗时间:


从图上可以看出,消耗的时间大概就是viewCach的40%左右的时间,这样大大优化了ListView.

0 0
原创粉丝点击