Listview、GridView反复调用position=0的问题

在使用Listview 、GridView的过程中会发现 adapter的getView方法中会创建好多次position=0的控件,这是为什么呢,下面让我们从源码部分分析一下:

GridView 和Listview都是继承AbListview的,那么我们来看看Ablistview

其中

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Sets up mListPadding
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    if (widthMode == MeasureSpec.UNSPECIFIED) {
        if (mColumnWidth > 0) {
            widthSize = mColumnWidth + mListPadding.left + mListPadding.right;
        } else {
            widthSize = mListPadding.left + mListPadding.right;
        }
        widthSize += getVerticalScrollbarWidth();
    }
    
    int childWidth = widthSize - mListPadding.left - mListPadding.right;
    boolean didNotInitiallyFit = determineColumns(childWidth);

    int childHeight = 0;
    int childState = 0;

    mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
    final int count = mItemCount;
    if (count > 0) {//测量高度的时候没次都会调用第一个ITem来测量
        final View child = obtainView(0, mIsScrap);

        AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
        if (p == null) {
            p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
            child.setLayoutParams(p);
        }
        p.viewType = mAdapter.getItemViewType(0);
        p.isEnabled = mAdapter.isEnabled(0);
        p.forceAdd = true;

        int childHeightSpec = getChildMeasureSpec(
                MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
                        MeasureSpec.UNSPECIFIED), 0, p.height);
        int childWidthSpec = getChildMeasureSpec(
                MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
        child.measure(childWidthSpec, childHeightSpec);

        childHeight = child.getMeasuredHeight();
        childState = combineMeasuredStates(childState, child.getMeasuredState());

        if (mRecycler.shouldRecycleViewType(p.viewType)) {
            mRecycler.addScrapView(child, -1);
        }
    }
    
    if (heightMode == MeasureSpec.UNSPECIFIED) {
        heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                getVerticalFadingEdgeLength() * 2;
    }

    if (heightMode == MeasureSpec.AT_MOST) {
        int ourSize =  mListPadding.top + mListPadding.bottom;
       
        final int numColumns = mNumColumns;
        for (int i = 0; i < count; i += numColumns) {
            ourSize += childHeight;
            if (i + numColumns < count) {
                ourSize += mVerticalSpacing;
            }
            if (ourSize >= heightSize) {
                ourSize = heightSize;
                break;
            }
        }
        heightSize = ourSize;
    }

    if (widthMode == MeasureSpec.AT_MOST && mRequestedNumColumns != AUTO_FIT) {
        int ourSize = (mRequestedNumColumns*mColumnWidth)
                + ((mRequestedNumColumns-1)*mHorizontalSpacing)
                + mListPadding.left + mListPadding.right;
        if (ourSize > widthSize || didNotInitiallyFit) {
            widthSize |= MEASURED_STATE_TOO_SMALL;
        }
    }

    setMeasuredDimension(widthSize, heightSize);
    mWidthMeasureSpec = widthMeasureSpec;、

主要看红色字体部分,当item的个数>0的时候,会执行下边这句
 final View child = obtainView(0, mIsScrap);

接下来看obtainView方法:

View obtainView(int position, boolean[] isScrap) {
    Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView");   
   child = mAdapter.getView(position, scrapView, this);
    return child;
}
看到这里就明白了为什么会反复带哦用position=0的了吧,就是在绘制listview的高度的时候,他会根据第一条的高度绘制,也就是position=0的item,那么知道了问题,我们该如何去解决呢,下边以Listview为例:GridView同样的道理

我们无法改变Listview父类的一些方法,那我们自定义一个Listview不让其继承自AbListview 不就可以了嘛,

我们自定义一个Listview 让其继承LInearLayout,其adapter跟平时的Listview一样即可。

public class DemoListView extends LinearLayout {
    private BaseAdapter mAdapter;
    private MyOnItemClickListener itemClickListener;
    private MyOnItemLongClickListener itemLongClickListener;

    public DemoListview(Context context) {
        super(context);
        init();
    }

    public DemoListview(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setOrientation(VERTICAL);
    }

    public void setAdapter(BaseAdapter adapter) {
        this.mAdapter = adapter;
        notifyChange();
    }

    public void notifyChange() {
        removeAllViews();
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        int itemCount = mAdapter.getCount();
        for (int i = 0; i < itemCount; i++) {

            LinearLayout layout = new LinearLayout(getContext());
            layout.setOrientation(VERTICAL);
            layout.setLayoutParams(params);
            View view = mAdapter.getView(i, null, null);
            layout.addView(view);
            if (i < itemCount - 1) {
                layout.addView(getLine());
            }
            addView(layout);

            final Object objects = mAdapter.getItem(i);
            final int finalI = i;
            view.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    itemClickListener.onItemClick(finalI, objects);
                }
            });
            view.setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    itemLongClickListener.onItemLongClick(finalI, objects);
                    return false;
                }
            });

        }
    }

    private TextView getLine() {
        LayoutParams p = new LayoutParams(LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.border_with));
        TextView lineView = new TextView(getContext());
        lineView.setBackgroundColor(getResources().getColor(R.color.RGB_CCD1D9));
        lineView.setLayoutParams(p);
        return lineView;
    }

    public void setOnItemClickListener(MyOnItemClickListener listener) {
        this.itemClickListener = listener;
    }

    public void setonItemLongClickListener(MyOnItemLongClickListener listener) {
        this.itemLongClickListener = listener;
    }

    public interface MyOnItemClickListener {
        public void onItemClick(int position, Object objects);
    }

    public interface MyOnItemLongClickListener {
        public void onItemLongClick(int positon, Object object);
    }

}





你可能感兴趣的:(Android)