关于ListView适配器getView()多次执行

在使用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;
}

 

这样就能彻底解决多次调用问题

转载于:https://my.oschina.net/u/3698786/blog/1920647

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值