首页 > 代码库 > Android性能优化之ListView缓存机制

Android性能优化之ListView缓存机制

要想优化ListView首先要了解它的工作原理,列表的显示需要三个元素:ListView、Adapter、显示的数据;

这里的Adapter就是用到了适配器模式,不管传入的是什么View在ListView中都能显示出来。

下面简单说下上图的原理:

1、如果你有几千几万甚至更多的选项(item)时,其中只有可见的项目(满屏显示的Item数目)存在内存(说的优化就是说在内存中的优化!)中,其他的在Recycler中

2、ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的,第一次都是为空的,只要显示过了convertView都不为空,会保存在Recycler中

3、当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图,省去了inflate和findViewById的时间,性能就得到了优化。


了解了它的工作原理后,我们就可以重复利用convertView,只要不为空就直接使用,改变它的内容就行了。

使用ListView的时候都会搭配一个Adapter,为了使得性能更优,ListView会缓存行item(某行对应的View)。ListView通过Adapter的getView函数获得每行的item。

[java] view plaincopy
  1. package com.dzt.listviewdemo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Context;  
  7. import android.os.Bundle;  
  8. import android.view.LayoutInflater;  
  9. import android.view.View;  
  10. import android.view.ViewGroup;  
  11. import android.widget.BaseAdapter;  
  12. import android.widget.ImageView;  
  13. import android.widget.ListView;  
  14. import android.widget.TextView;  
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.     private ListAdapter adapter;  
  19.     private ListView lv = null;  
  20.     private ArrayList<String> list = new ArrayList<String>();  
  21.   
  22.     @Override  
  23.     protected void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         setContentView(R.layout.activity_main);  
  26.         lv = (ListView) findViewById(R.id.lv_list);  
  27.         adapter = new ListAdapter();  
  28.         for (int i = 0; i < 100; i++) {  
  29.             list.add("item " + i);  
  30.         }  
  31.         lv.setAdapter(adapter);  
  32.     }  
  33.   
  34.     private class ListAdapter extends BaseAdapter {  
  35.   
  36.         private LayoutInflater mInflater;  
  37.   
  38.         ListAdapter() {  
  39.             mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  40.         }  
  41.   
  42.         @Override  
  43.         public int getCount() {  
  44.             // TODO Auto-generated method stub  
  45.             return list.size();  
  46.         }  
  47.   
  48.         @Override  
  49.         public Object getItem(int position) {  
  50.             // TODO Auto-generated method stub  
  51.             return list.get(position);  
  52.         }  
  53.   
  54.         @Override  
  55.         public long getItemId(int position) {  
  56.             // TODO Auto-generated method stub  
  57.             return position;  
  58.         }  
  59.   
  60.         @Override  
  61.         public View getView(int position, View convertView, ViewGroup parent) {  
  62.             // TODO Auto-generated method stub  
  63.             System.out.println("getView " + position + "    " + convertView);  
  64.             viewHolder holder = null;  
  65.             if (convertView == null) {  
  66.                 convertView = mInflater.inflate(R.layout.item, null);  
  67.                 holder = new viewHolder();  
  68.                 holder.text = (TextView) convertView.findViewById(R.id.tv_text);  
  69.                 holder.image = (ImageView) convertView  
  70.                         .findViewById(R.id.iv_img);  
  71.                 convertView.setTag(holder);  
  72.             } else {  
  73.                 holder = (viewHolder) convertView.getTag();  
  74.             }  
  75.             holder.text.setText(list.get(position));  
  76.             if (position % 2 == 0) {  
  77.                 holder.image.setImageResource(R.drawable.ic_launcher);  
  78.             } else {  
  79.                 holder.image.setImageResource(R.drawable.icon);  
  80.             }  
  81.   
  82.             return convertView;  
  83.         }  
  84.   
  85.     }  
  86.   
  87.     /** 
  88.      * 使用一个类来保存Item中的元素 
  89.      *  
  90.      * @author Administrator 
  91.      *  
  92.      */  
  93.     public static class viewHolder {  
  94.         public TextView text;  
  95.         public ImageView image;  
  96.     }  
  97. }  

运行效果


第一次打印的结果convertView都是为null


滑动ListView后的打印


从上面的打印消息可以看出,Recycler中会保存七个convertView对象用来显示Item,不管你有上千个Item,也只会创建显示满屏的convertView,这就大大节省了内存,对viewHolder的Tag的使用也大大节省了性能开销

 

Android性能优化之ListView缓存机制