在使用ListView显示数据的时候,定义一个适配器,然后重写getView()方法,这时通过LOG日志分析会发现getView()方法会被执行多次。通过上网查询资料得出
原因在于View在Draw的时候分为两个阶段,measure和layout,在measure阶段得时候,主要是为了计算两个参数,height和width,这是一个递归的过程,DecorView开始依次调用自己元素的measure,计算完成两个参数就开始layout,然后调用draw,对于ListView,每一个Item都会调用measure(),而在这个过程中getView()和getCont()会被调用,而且根据用户的需求,可能有多次调用
多组调用的原因:
这是由于layout中定义的ListView或者其父元素的height和width的属性决定了,fill_parent,计算会简单一点,但是Wrap_content的计算会多一点,至于自适应会一直考量Item的宽和高,根据内容,计算高度,这个measure可能会反复执行。
解决方法
解决方法,就是listview的大小要确定,例如使用match_parent。
方法一: 在listview外面套一层RelativeLayout,将listview高度设置为match_parent。
方法二: 在listview外面套一层 LinearLayout,将listview高度设置为0dip。
weight设为1。
这样简单的listview是有效的,但是item如果是复杂的xml,很难实现,或者说无法实现。如果是scrollview嵌套listview和gridview也不会成功。
究其原因,无非是listview要动态计算有多少个view显示在里面,所以需要多次onMeasure,最后才onLayout,而onMeasure可能需要执行多次。这不就行了,我们在adapt里面的getview中,判断是否在onmeasure里,如果在。(在adapter的getView()方法中,对isOnMeasure()的值进行判断,如果为ture,提前return convertView;)
首先重写 listview
public class NoScrollListview extends ListView{ //设置判断来防止重复执行getView(); public boolean isOnMeasure = false; public NoScrollListview(Context context) { super(context); } public NoScrollListview(Context context, AttributeSet attrs) { super(context, attrs); } /** * 设置不滚动 */ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { isOnMeasure = true; int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { isOnMeasure = false; super.onLayout(changed, l, t, r, b); } }
然后在Adapter中判断
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder vh; if (convertView == null) { convertView = inflater.inflate(R.layout.inflate_griditem_mainpage_wall_and_lock, null); vh = new ViewHolder(); vh.iv = (ImageView) convertView.findViewById(R.id.image_griditem2); convertView.setTag(vh); }else { vh = (ViewHolder) convertView.getTag(); } //关键代码 if (parent instanceof MyGridView) { if (((MyGridView)parent).isOnMeasure) { return convertView; } } String url = (String)getItem(position); HttpUtil.loadImage(context, Stringutil.get208x312(url), vh.iv); vh.iv.setOnClickListener(new MyClickListener(Stringutil.get480x800(url))); num++; Log.i("Cat", "getView() : Main = "+num+""); return convertView; }
这样就能彻底解决多次调用问题