关于ListView的getView方法被多次重复调用的问题

package com.pxy.demo.adapter;

import java.util.ArrayList;

import com.pxy.demo.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;

public class MyAdapter extends BaseAdapter{

	private ArrayList list;
	private Context context;
	
	public MyAdapter(Context context,ArrayList list) {
		super();
		this.context = context;
		this.list = list;
	}

	@Override
	public int getCount() {
		return list == null? 0 :list.size();
	}

	@Override
	public Object getItem(int position) {
		return null;
	}

	@Override
	public long getItemId(int position) {
		return 0;
	}

	@Override
	public View getView(int position, View v, ViewGroup parent) {
		ViewHolder holder = null;
		System.out.println("view = "+v + "  position = " + position);
			if(v == null){
				System.out.println("view = null 时进入方法");
				holder = new ViewHolder();
				v = LayoutInflater.from(context).inflate(R.layout.item, null);
				holder.mButton = (Button) v.findViewById(R.id.btn);
				v.setTag(holder);
			}else{
				holder = (ViewHolder) v.getTag();
		}
		String str = list.get(position);
		if(str!=null){
			holder.mButton.setText(str);
		}
		return v;
	}
	
	private class ViewHolder {
       Button mButton;
	}

}


运行时会发现getView会被重复调用多次,假设list.size()=10,getView被调用的次数会大于10,原因是当ListView的高度是固定的或者match_parent的时候,listview很容易就能计算出容器内可以显示多少行。但如果我们使用了“wrap_content,只有在屏幕内控件完全加载后才知道到底能显示多少行数据时,ListView自身便会做一些尝试性计算,就会导致重复调用多次getView(具体请看log输出日志)。

具体原因:View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两个参数后就开始layout,最后再是draw的调用。对于ListView,当然每一个Item都会被调用measure方法,而在这个过程中getView和getCount会被调用,而且看用户的需求,
可能会有很多次调用。而为什么会有很多组次调用呢?问题就在于在layout中的决定ListView或者它的父元素的height和width属性的定义了。match_parent会好一点,计算方法会比较简单,只要跟父元素的大小相似就行,但是即使是match_parent,也不能给View当饭吃,还是要计算出来具体的dip,所以measure还是会被调用,只是可能比wrap_content的少一点。至于自适应的它会一直考量它的宽和高,根据内容(也就是它的子Item)计算宽高。可能这个measure过程会反复执行,如果父元素也是wrap_content,这个过程会更加漫长。所以,解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。

listview,gridview,有时候getview会调用多次,特别是把listview放在viewpager中,很容易卡顿
网上的方法往往只是说,把listview的height固定住或者fill_parent,其实这样简单的listview是有效的,但是item如果是复杂的xml,很难实现,或者说无法实现。
究其原因,无非是listview要动态计算有多少个view显示在里面,所以需要多次onMeasure,最后才onLayout,而onMeasure可能需要执行多次
这不就行了,我们在adapt里面的getview中,判断是否在onmeasure里,如果在,那么仅仅mInflater.inflate(R.layout.XXX),然后立刻返回这个
convertView,如果不在onmeasure里,那么再去真正的onlayout.
结合这种方法,成功解决了卡顿问题..

你可能感兴趣的:(android)