RecyclerView(二) 一、緩存 二、緩存 mCachedViews

一、緩存

二、緩存 mCachedViews

執行LinearLayoutManager.onLayoutChildren方法

public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    ...
    detachAndScrapAttachedViews(recycler);
    ...
}
        public void detachAndScrapAttachedViews(@NonNull Recycler recycler) {
            final int childCount = getChildCount();
            for (int i = childCount - 1; i >= 0; i--) {
                final View v = getChildAt(i);
                scrapOrRecycleView(recycler, i, v);
            }
        }
        private void scrapOrRecycleView(Recycler recycler, int index, View view) {
            final ViewHolder viewHolder = getChildViewHolderInt(view);
            if (viewHolder.shouldIgnore()) {
                if (DEBUG) {
                    Log.d(TAG, "ignoring view " + viewHolder);
                }
                return;
            }
            if (viewHolder.isInvalid() && !viewHolder.isRemoved()
                    && !mRecyclerView.mAdapter.hasStableIds()) {
//將index的view從mHiddenViews移除的動作
                removeViewAt(index);
//向 mCachedViews 或 Pool 中添加
                recycler.recycleViewHolderInternal(viewHolder);
            } else {
 //設置RecyclerView這個位置的view的parent爲null, 並標記ViewHolder爲FLAG_TMP_DETACHED
                detachViewAt(index);
//添加到mAttachedScrap 或 mCachedViews集合中
                recycler.scrapView(view);
                mRecyclerView.mViewInfoStore.onViewDetached(viewHolder);
            }
        }

然後在RecyclerView的集合中緩存

2.1、 mCachedViews 或 Pool 緩存

    void recycleViewHolderInternal(RecyclerView.ViewHolder holder) {
        final boolean transientStatePreventsRecycling = holder
                .doesTransientStatePreventRecycling();
        @SuppressWarnings("unchecked")
        final boolean forceRecycle = mAdapter != null
                && transientStatePreventsRecycling
                && mAdapter.onFailedToRecycleView(holder);
        boolean cached = false;
        boolean recycled = false;
        if (DEBUG && mCachedViews.contains(holder)) {
            throw new IllegalArgumentException("cached view received recycle internal? "
                    + holder + exceptionLabel());
        }
        if (forceRecycle || holder.isRecyclable()) {
            if (mViewCacheMax > 0
                    && !holder.hasAnyOfTheFlags(RecyclerView.ViewHolder.FLAG_INVALID
                    | RecyclerView.ViewHolder.FLAG_REMOVED
                    | RecyclerView.ViewHolder.FLAG_UPDATE
                    | RecyclerView.ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
                // Retire oldest cached view
                int cachedViewSize = mCachedViews.size();
                //大於緩存的最大值 mViewCacheMax = 2, CacheView 把老的移除集合,放入 pool 中
                if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
                    //取出集合的第一個元素放入 pool 中
                    recycleCachedViewAt(0);
                    //緩存的個數減一
                    cachedViewSize--;
                }

                int targetCacheIndex = cachedViewSize;
                if (ALLOW_THREAD_GAP_WORK
                        && cachedViewSize > 0
                        && !mPrefetchRegistry.lastPrefetchIncludedPosition(holder.mPosition)) {
                    // when adding the view, skip past most recently prefetched views
                    int cacheIndex = cachedViewSize - 1;
                    while (cacheIndex >= 0) {
                        int cachedPos = mCachedViews.get(cacheIndex).mPosition;
                        if (!mPrefetchRegistry.lastPrefetchIncludedPosition(cachedPos)) {
                            break;
                        }
                        cacheIndex--;
                    }
                    targetCacheIndex = cacheIndex + 1;
                }
                //加入 mCachedViews 集合
                mCachedViews.add(targetCacheIndex, holder);
                cached = true;
            }
            if (!cached) {
                // 添加到Pool中
                addViewHolderToRecycledViewPool(holder, true);
                recycled = true;
            }
        } else {
            if (DEBUG) {
                Log.d(TAG, "trying to recycle a non-recycleable holder. Hopefully, it will "
                        + "re-visit here. We are still removing it from animation lists"
                        + exceptionLabel());
            }
        }
        mViewInfoStore.removeViewHolder(holder);
        if (!cached && !recycled && transientStatePreventsRecycling) {
            holder.mOwnerRecyclerView = null;
        }
    }
  • 接下來看向 pool 中添加的步驟
    void addViewHolderToRecycledViewPool(@NonNull RecyclerView.ViewHolder holder, boolean dispatchRecycled) {
        clearNestedRecyclerViewIfNotNested(holder);
        View itemView = holder.itemView;
        if (mAccessibilityDelegate != null) {
            AccessibilityDelegateCompat itemDelegate = mAccessibilityDelegate.getItemDelegate();
            AccessibilityDelegateCompat originalDelegate = null;
            if (itemDelegate instanceof RecyclerViewAccessibilityDelegate.ItemDelegate) {
                originalDelegate =
                        ((RecyclerViewAccessibilityDelegate.ItemDelegate) itemDelegate)
                                .getAndRemoveOriginalDelegateForItem(itemView);
            }
            // Set the a11y delegate back to whatever the original delegate was.
            ViewCompat.setAccessibilityDelegate(itemView, originalDelegate);
        }
        if (dispatchRecycled) {
            dispatchViewRecycled(holder);
        }
        holder.mOwnerRecyclerView = null;
        getRecycledViewPool().putRecycledView(holder);
    }
    public void putRecycledView(RecyclerView.ViewHolder scrap) {
        final int viewType = scrap.getItemViewType();
        final ArrayList<RecyclerView.ViewHolder> scrapHeap = getScrapDataForType(viewType).mScrapHeap;
        if (mScrap.get(viewType).mMaxScrap <= scrapHeap.size()) {
            return;
        }
        if (DEBUG && scrapHeap.contains(scrap)) {
            throw new IllegalArgumentException("this scrap item already exists");
        }
        scrap.resetInternal();
        scrapHeap.add(scrap);
    }

調用RecyclerView.RecycledViewPool中的方法getScrapDataForType

    private ScrapData getScrapDataForType(int viewType) {
        ScrapData scrapData = mScrap.get(viewType);
        if (scrapData == null) {
            scrapData = new ScrapData();
            mScrap.put(viewType, scrapData);
        }
        return scrapData;
    }

2.2、mAttachedScrap 或 mCachedViews 緩存

    void scrapView(View view) {
        final ViewHolder holder = getChildViewHolderInt(view);
        if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
                || !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {
            if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) {
                throw new IllegalArgumentException("Called scrap view with an invalid view."
                        + " Invalid views cannot be reused from scrap, they should rebound from"
                        + " recycler pool." + exceptionLabel());
            }
            holder.setScrapContainer(this, false);
            mAttachedScrap.add(holder);
        } else {
            if (mChangedScrap == null) {
                mChangedScrap = new ArrayList<ViewHolder>();
            }
            holder.setScrapContainer(this, true);
            mChangedScrap.add(holder);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章