要想优化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。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | packagecom.dzt.listviewdemo;importjava.util.ArrayList;importandroid.app.Activity;importandroid.content.Context;importandroid.os.Bundle;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.BaseAdapter;importandroid.widget.ImageView;importandroid.widget.ListView;importandroid.widget.TextView;publicclassMainActivity extendsActivity {    privateListAdapter adapter;    privateListView lv = null;    privateArrayList<string> list = newArrayList<string>();    @Override    protectedvoidonCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        lv = (ListView) findViewById(R.id.lv_list);        adapter = newListAdapter();        for(inti = 0; i < 100; i++) {            list.add(item  + i);        }        lv.setAdapter(adapter);    }    privateclassListAdapter extendsBaseAdapter {        privateLayoutInflater mInflater;        ListAdapter() {            mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);        }        @Override        publicintgetCount() {            // TODO Auto-generated method stub            returnlist.size();        }        @Override        publicObject getItem(intposition) {            // TODO Auto-generated method stub            returnlist.get(position);        }        @Override        publiclonggetItemId(intposition) {            // TODO Auto-generated method stub            returnposition;        }        @Override        publicView getView(intposition, View convertView, ViewGroup parent) {            // TODO Auto-generated method stub            System.out.println(getView  + position +      + convertView);            viewHolder holder = null;            if(convertView == null) {                convertView = mInflater.inflate(R.layout.item, null);                holder = newviewHolder();                holder.text = (TextView) convertView.findViewById(R.id.tv_text);                holder.image = (ImageView) convertView                        .findViewById(R.id.iv_img);                convertView.setTag(holder);            } else{                holder = (viewHolder) convertView.getTag();            }            holder.text.setText(list.get(position));            if(position % 2== 0) {                holder.image.setImageResource(R.drawable.ic_launcher);            } else{                holder.image.setImageResource(R.drawable.icon);            }            returnconvertView;        }    }    /**     * 使用一个类来保存Item中的元素     *      * @author Administrator     *      */    publicstaticclassviewHolder {        publicTextView text;        publicImageView image;    }}</string></string> | 
运行效果

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

滑动ListView后的打印

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