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

在使用ListView显示数据的时候,定义一个适配器,而后重写getView()方法,这时经过LOG日志分析会发现getView()方法会被执行屡次。经过上网查询资料得出ide

缘由在于View在Draw的时候分为两个阶段,measure和layout,在measure阶段得时候,主要是为了计算两个参数,height和width,这是一个递归的过程,DecorView开始依次调用本身元素的measure,计算完成两个参数就开始layout,而后调用draw,对于ListView,每个Item都会调用measure(),而在这个过程当中getView()和getCont()会被调用,并且根据用户的需求,可能有屡次调用url

多组调用的缘由:spa

这是因为layout中定义的ListView或者其父元素的height和width的属性决定了,fill_parent,计算会简单一点,可是Wrap_content的计算会多一点,至于自适应会一直考量Item的宽和高,根据内容,计算高度,这个measure可能会反复执行。日志

解决方法

解决方法,就是listview的大小要肯定,例如使用match_parent。 
方法一: 
在listview外面套一层RelativeLayout,将listview高度设置为match_parent。code

方法二: 
在listview外面套一层 LinearLayout,将listview高度设置为0dip。weight设为1。xml

这样简单的listview是有效的,可是item若是是复杂的xml,很难实现,或者说没法实现。若是是scrollview嵌套listview和gridview也不会成功。递归

究其缘由,无非是listview要动态计算有多少个view显示在里面,因此须要屡次onMeasure,最后才onLayout,而onMeasure可能须要执行屡次。这不就好了,咱们在adapt里面的getview中,判断是否在onmeasure里,若是在。(在adapter的getView()方法中,对isOnMeasure()的值进行判断,若是为ture,提早return convertView;)ip

首先重写 listviewget

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中判断it

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;
}

 

这样就能完全解决屡次调用问题

相关文章
相关标签/搜索