ListView的性能优化方面可以看出一个安卓开发者的基本素养,ListView控件绝对是无处不在;
这次的项目用到了多个视图显示到ListView中,所以借此总结一下;
列表控件可能有存在成千上万的视图显示,如果没有缓存视图是绝对不可能的;
下面看看ListView的工作原理图:
当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,改变视图中的数据而不重新创建视图,达到改变视图内容的效果;
即:刚移出列表的视图会跑到队尾被重用;
单个视图文件
public class SingleViewAdapter extends BaseAdapter{
private Context context;
private int size = 50;
private String tag = "SingleViewAdapter";
public SingleViewAdapter(Context context) {
super();
this.context = context;
}
@Override
public int getCount() {
return size;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.listitem3, null);
holder = new ViewHolder();
holder.imageview = (ImageView) convertView.findViewById(R.id.imageview);
holder.textview3 = (TextView) convertView.findViewById(R.id.textview3);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.textview3.setText("position="+position);
Log.i(tag, "convertView="+convertView.hashCode());
return convertView;
}
private class ViewHolder{
TextView textview3;
ImageView imageview;
}
}
上面适配器为一直重用一个视图,输出日志为:
01-02 09:10:26.910: I/SingleViewAdapter(26514): convertView=1107144112
01-02 09:10:26.910: I/SingleViewAdapter(26514): convertView=1107150552
01-02 09:10:26.910: I/SingleViewAdapter(26514): convertView=1107155280
01-02 09:10:26.920: I/SingleViewAdapter(26514): convertView=1107160008
01-02 09:10:26.930: I/SingleViewAdapter(26514): convertView=1107164736
01-02 09:10:26.930: I/SingleViewAdapter(26514): convertView=1107169464
01-02 09:10:26.940: I/SingleViewAdapter(26514): convertView=1107174192
01-02 09:10:46.130: I/SingleViewAdapter(26514): convertView=1107207280
01-02 09:10:46.220: I/SingleViewAdapter(26514): convertView=1107144112
01-02 09:10:46.280: I/SingleViewAdapter(26514): convertView=1107150552
01-02 09:10:46.380: I/SingleViewAdapter(26514): convertView=1107155280
01-02 09:10:46.600: I/SingleViewAdapter(26514): convertView=1107160008
01-02 09:10:47.790: I/SingleViewAdapter(26514): convertView=1107164736
01-02 09:10:48.020: I/SingleViewAdapter(26514): convertView=1107169464
正好验证了上面的原理;
多个视图文件
当有多个需要重用的时候,明显的不能重用一个视图,这种情况下需要我们重写多两个方法:
public int getItemViewType(int position) ;
public int getViewTypeCount() ;
public class DemoAdapter extends BaseAdapter {
private LayoutInflater inflater;
private int size = 50;
private String tag = "DemoAdapter";
public DemoAdapter(Context context) {
super();
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return size;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public int getItemViewType(int position) {
Log.i(tag, "getItemViewType#"+position);
return position%3;
}
@Override
public int getViewTypeCount() {
Log.i(tag, "getViewTypeCount#3");
return 3;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder1 holder1 = null;
ViewHolder2 holder2 = null;
ViewHolder3 holder3 = null;
//getItemViewType(position);
if (null == convertView) {
switch (position % 3) {
case 0:
convertView = inflater.inflate(R.layout.listitem1, parent,
false);
Log.i(tag,"解析布局1");
holder1 = new ViewHolder1();
holder1.checkBox = (CheckBox) convertView.findViewById(R.id.checkBox1);
holder1.textView=(TextView) convertView.findViewById(R.id.textView1);
convertView.setTag(holder1);
break;
case 1:
convertView = inflater.inflate(R.layout.listitem2, parent,
false);
Log.i(tag,"解析布局2");
holder2 = new ViewHolder2();
holder2.textView = (TextView) convertView.findViewById(R.id.textview2);
convertView.setTag(holder2);
break;
case 2:
convertView = inflater.inflate(R.layout.listitem3, parent,
false);
Log.i(tag,"解析布局3");
holder3 = new ViewHolder3();
holder3.imageView = (ImageView) convertView.findViewById(R.id.imageview);
holder3.textView = (TextView) convertView.findViewById(R.id.textview3);
convertView.setTag(holder3);
break;
default:
break;
}
} else {
switch (position % 3) {
case 0:
holder1 = (ViewHolder1) convertView.getTag();
break;
case 1:
holder2 = (ViewHolder2) convertView.getTag();
break;
case 2:
holder3 = (ViewHolder3) convertView.getTag();
break;
default:
break;
}
}
switch (position % 3) {
case 0:
holder1.textView.setText(Integer.toString(position));
holder1.checkBox.setChecked(true);
break;
case 1:
holder2.textView.setText(Integer.toString(position));
break;
case 2:
holder3.textView.setText(Integer.toString(position));
holder3.imageView.setBackgroundResource(R.drawable.ic_launcher);
break;
default:
break;
}
Log.i(tag, position+"|"+convertView.hashCode());
return convertView;
}
class ViewHolder1 {
CheckBox checkBox;
TextView textView;
}
class ViewHolder2 {
TextView textView;
}
class ViewHolder3 {
ImageView imageView;
TextView textView;
}
}
getItemViewType()中返回的值要看齐getViewTypeCount()的值,如果不一致容易导致数组溢出;
所以一般上面代码中的取余写法能够较为有代表性的保证数组不溢出;
通过多种视图的方式也可以实现下面这样的目录形式,自己修改就好:
本文来自于CSDN博客,转载请联系作者;
注明出处http://blog.csdn.net/dreamintheworld/article/details/39931585