对RecycleBin的理解

两个重要的域

private View[] mActiveViews = new View[0]; //屏幕上显示的Item

private ArrayList<View>[] mScrapViews;//移除屏幕的Item

 重要的方法

public void markChildrenDirty()    //    该方法标记出移除屏幕的item    用forcelayout函数。(该函数没找到)

void fillActiveViews(int childCount, int firstActivePosition)//通过传入的firstActiovePosition来初始化mActiveViews数组

发现一个问题

int[] test1 = { 1, 1, 1, 1 };
int[] test2 = test1;
test2[0] = 0;

会发现test1   test2都变了,因为=赋值是把地址指针赋值了,所以两个数组指向的其实是一个东西。

而在recycleBin中经常这样用:

final View[] activeViews = mActiveViews;

在对activeViews进行操作;不知道是不是会有性能上的优势。而且final的值是不能变得啊,为什么会写activeViews[index] = null;(实际上值是可变的)


重要函数:将移出屏幕的view加入scrapyview。参数scrap是被移出的view,position是其在父类中的位置。

void addScrapView(View scrap, int position) {
            final AbsListView.LayoutParams lp = (AbsListView.LayoutParams) scrap.getLayoutParams();
            if (lp == null) {
                // Can't recycle, but we don't know anything about the view.
                // Ignore it completely.

//啥也不知道,直接就没法加
                return;
            }


            lp.scrappedFromPosition = position;


            // Remove but don't scrap header or footer views, or views that
            // should otherwise not be recycled.
            final int viewType = lp.viewType;
            if (!shouldRecycleViewType(viewType)) {
                // Can't recycle. If it's not a header or footer, which have
                // special handling and should be ignored, then skip the scrap
                // heap and we'll fully detach the view later.

//如果不为header或者footer,就skip the scrapy,先跳过,将其储存在一个list中,等一会再detach(此处意思应该为拆分?)
                if (viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
                    getSkippedScrap().add(scrap);
                }
                return;
            }


            scrap.dispatchStartTemporaryDetach();


            // The the accessibility state of the view may change while temporary
            // detached and we do not allow detached views to fire accessibility
            // events. So we are announcing that the subtree changed giving a chance
            // to clients holding on to a view in this subtree to refresh it.

    //不懂,无视
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);


            // Don't scrap views that have transient state.

   //什么事transient state? transient意为短暂的,暂时的。
            final boolean scrapHasTransientState = scrap.hasTransientState();
            if (scrapHasTransientState) {
                if (mAdapter != null && mAdapterHasStableIds) {
                    // If the adapter has stable IDs, we can reuse the view for
                    // the same data.

    //此处有意思,如果每个view的lp都有单独的id,那么就把这些个view和其id存在一个表里,下次再读到这个id时就取用          // mTransientStateViewsById中的数据就好       
                    if (mTransientStateViewsById == null) {
                        mTransientStateViewsById = new LongSparseArray<>();
                    }
                    mTransientStateViewsById.put(lp.itemId, scrap);
                } else if (!mDataChanged) {
                    // If the data hasn't changed, we can reuse the views at
                    // their old positions.

    //在没有stableid的情况下,如果数据不变(这是怎么判断的呢?)着直接可以用原位置上的view
                    if (mTransientStateViews == null) {
                        mTransientStateViews = new SparseArray<>();
                    }
                    mTransientStateViews.put(position, scrap);
                } else {
                    // Otherwise, we'll have to remove the view and start over.

    //其他情况下就只能把这个transientview加入到skippedscrapy中去了。
                    getSkippedScrap().add(scrap);
                }
            } else {

//如果不在transient状态下
                if (mViewTypeCount == 1) {
                    mCurrentScrap.add(scrap);
                } else {
                    mScrapViews[viewType].add(scrap);
                }


                if (mRecyclerListener != null) {
                    mRecyclerListener.onMovedToScrapHeap(scrap);
                }
            }
        }


//重要函数,参数scrapViews是分两种情况,如果是一个布局就是mCurrentScrap,如果是多个布局就是mScrapyViews[]

 private View retrieveFromScrap(ArrayList<View> scrapViews, int position) {
            final int size = scrapViews.size();
            if (size > 0) {
                // See if we still have a view for this position or ID.
                for (int i = 0; i < size; i++) {
                    final View view = scrapViews.get(i);
                    final AbsListView.LayoutParams params =
                            (AbsListView.LayoutParams) view.getLayoutParams();


                    if (mAdapterHasStableIds) {

//遍历数组,如果是view有stableId 的情况下,则将同id 的view移除scrapviews。
                        final long id = mAdapter.getItemId(position);
                        if (id == params.itemId) {
                            return scrapViews.remove(i);
                        }
                    } else if (params.scrappedFromPosition == position) {

//如果是从同一个位置scrap掉的,则返回这个位置的scrapview
                        final View scrap = scrapViews.remove(i);
                        clearAccessibilityFromScrap(scrap);
                        return scrap;
                    }
                }

//如果都不是,则返回最后的一个scrap
                final View scrap = scrapViews.remove(size - 1);
                clearAccessibilityFromScrap(scrap);
                return scrap;
            } else {
                return null;
            }
        }


//此处是转载http://blog.csdn.net/linghu_java/article/details/39496921的一段分析

 1. 如果有view.scrappedFromPosition = position的,直接返回该view

        2. 否则返回mScrapView中最后一个;

        3. 如果缓存中没有view,则返回null

        a. 第三种情况,这个最简单:

一开始,listview稳定后,显示N个,此时mScrapView中是没有缓存view的,当我们向上滚动一小段距离(第一个此时仍显示部分),新的view将会显示,此时listview会调用Adapter.getView,但是缓存中没有,因此convertViewnull,所以,我们得分配一块内存来创建新的convertView

        b. 第二种情况:

a中,我们继续向上滚动,直接第一个view完全移出屏幕(假设没有新的item),此时,第一个view就会被detach,并被加入到mScrapView中;然后,我们还继续向上滚动,直接后面又将要显示新的item view时,此时,系统会从mScrapView中找position对应的View,显然,是找不到的,则将从mScrapView中,取最后一个缓存的view传递给convertView

        c. 第一种情况:

紧接着在b中,第一个被完全移出,加入到mScrapView中,且没有新增的itemlistview中,此时,缓存中就只有第一个view;然后,我此时向下滑动,则之前的第一个item,将被显示出来,此时,从缓存中查找position对应的view有没有,当然,肯定是找到了,就直接返回了。


在项目的工程实践中出现了第二种情况,我想是因为我在request之初将typelist置空,这时候会执行setadapter,但是这时候gettypecount函数返回为零,scrapview只会存一个scrap(即滑出列表的titleview),但这时应该生产一个footview,当然就会转型错误了。

//void scrapActiveViews()一个将所有ActivieView全部转移到ScrapView中的方法,暂时没看到在哪用





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值