ListView单个视图或多个视图重用问题

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值