ListView 中ItemView 的重用原理

在listview的重用view的原理是:将可视的view和非可视的view保存在两个数据结构中,分别指mActivityView和scrapView中,

mActivityView指的是,当前屏幕上显示的显示的View。

scrapView是指,屏幕上不显示的View,所有mActivityView都会转换成scrapView。

重用是把scrapView 传给Adapter.getView , 参数convertView 不为空就是从scrapView拿出的View。

public View getView(int position, View convertView,ViewGroup parent)

 

从代码分析可知,在listview中当有多种viewtype的时候,在adapter中继承设置getItemViewType方法可以更有效率 

ListView(extends AbsListView)
    private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
            boolean selected) {
        View child;
 
        if (!mDataChanged) {// 数据没有更新时,使用以前的view
            // Try to use an exsiting view for this position
            child = mRecycler.getActiveView(position);
            if (child != null) {
                // Found it -- we're using an existing child
                // This just needs to be positioned
                           
                setupChild(child, position, y, flow, childrenLeft, selected, true);
                return child;
            }
        }
             
        // Make a new view for this position, or convert an unused view if possible
        child = obtainView(position);
 
        // This needs to be positioned and measured
        setupChild(child, position, y, flow, childrenLeft, selected, false);
 
        return child;
    }
    View obtainView(int position) {
        View scrapView;
        // 查看回收站中是否有废弃无用的View,如果有,则使用它,无需New View。
        scrapView = mRecycler.getScrapView(position);
 
        View child;
 
        if (scrapView != null) { //此时说明可以从回收站中重新使用scrapView。
            child = mAdapter.getView(position, scrapView, this);
             if (child != scrapView) { // 没有使用处于回收站中的scrapView,还是New了一个View
                mRecycler.addScrapView(scrapView); // scrapView 仍然放入回收站
                if (mCacheColorHint != 0) {
                    child.setDrawingCacheBackgroundColor(mCacheColorHint);
                }
            }
 
        } else {
            child = mAdapter.getView(position, null, this);
            if (mCacheColorHint != 0) {
                child.setDrawingCacheBackgroundColor(mCacheColorHint);
            }
        }
 
        return child;
}

void trackMotionScroll(int deltaY, int incrementalDeltaY) {
        // 滚动时,不在可见范围内的item都放入回收站
            if (down) {
                final int top = listPadding.top - incrementalDeltaY;
                for (int i = 0; i < childCount; i++) {
                    final View child = getChildAt(i);
                    if (child.getBottom() >= top) {
                        break;
                    } else {
                        count++;
                        int position = firstPosition + i;
                        if (position >= headerViewsCount && position < footerViewsStart) {
                            mRecycler.addScrapView(child); //放入回收站
                        }
                    }
                }
            } else {
                final int bottom = getHeight() - listPadding.bottom - incrementalDeltaY;
                for (int i = childCount - 1; i >= 0; i--) {
                    final View child = getChildAt(i);
                    if (child.getTop() <= bottom) {
                        break;
                    } else {
                        start = i;
                        count++;
                        int position = firstPosition + i;
                        if (position >= headerViewsCount && position < footerViewsStart) {
                            mRecycler.addScrapView(child); //放入回收站
                        }
                    }
                }
            }
        }
    }

RecycleBin有2种方式存储View,ActiveViews和ScrapViews。ActiveViews是指显示在屏幕上的View,在一个Layout的开始部分。

通过建设, ActiveViews是显示当前信息。

在布局的最后,所有的ActiveViews将为ScrapViews。

ScrapViews的意思是,旧的View,可以使用adapter避免不必要的View

    class RecycleBin {
        private RecyclerListener mRecyclerListener;
  /**
第一个mActiveViews中的第一个View在ListView中的位置。
         */
        private int mFirstActivePosition;

        /**
屏幕中可见的View,在mActiveViews 中的View,最后都会到mScrapViews中。mActiveViews中存储着连续的可见的View,从第一个View,到最后一个可见的View
         */
        private View[] mActiveViews = new View[0];

        /**
存储在mScrapViews的View,将会被adapter 利用,作为convert view
         */
        private ArrayList<View>[] mScrapViews;
        private int mViewTypeCount;

        private ArrayList<View> mCurrentScrap;

        private ArrayList<View> mSkippedScrap;

        private SparseArray<View> mTransientStateViews;
        public void setViewTypeCount(int viewTypeCount) {
            if (viewTypeCount < 1) {
                throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
            }
            //noinspection unchecked
            ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
            for (int i = 0; i < viewTypeCount; i++) {
                scrapViews[i] = new ArrayList<View>();
            }
            mViewTypeCount = viewTypeCount;
            mCurrentScrap = scrapViews[0];
            mScrapViews = scrapViews;
        }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值