RecyclerView memory performance is superior, thanks to its unique caching mechanism. An issue left unresolved from Article 1: What is the highest priority Scrap View used for reusing table entries? This article tries to answer this question by reading the source code.

RecyclerView Cache mechanism This is the fourth article in the RecyclerView cache mechanism series.

  1. RecyclerView caching mechanism | how to reuse table?

  2. What RecyclerView caching mechanism | recycling?

  3. RecyclerView caching mechanism | recycling where?

  4. RecyclerView caching mechanism | scrap the view of life cycle

  5. RecyclerView animation principle | pre – layout, post – the relationship between the layout and scrap the cache

Final ArrayList

mAttachedScrap = new ArrayList<>(); . The best way to understand the purpose of a member variable is to “search for when it was accessed.” For the list structure it is equivalent to 1. When do I add content to the list? 2. When should I clear the list?

Add content

Search globally for where mAttachedScrap is accessed, only one of which calls mattachedScrape.add ():

public final class Recycler {
         // Recycle ViewHolder to the Scrap collection (MathedScrap or mChangedScrap),
        void scrapView(View view) {
            final ViewHolder holder = getChildViewHolderInt(view);
            if(holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID) || ! holder.isUpdated() || canReuseUpdatedViewHolder(holder)) { holder.setScrapContainer(this.false);
                // Add to the mAttachedScrap set
                mAttachedScrap.add(holder);
            } else {
                if (mChangedScrap == null) {
                    mChangedScrap = new ArrayList<ViewHolder>();
                }
                holder.setScrapContainer(this.true);
                // Add to the mChangedScrap setmChangedScrap.add(holder); }}}Copy the code

Continuing up the call chain:

public abstract static class LayoutManager {
        private void scrapOrRecycleView(Recycler recycler, int index, View view) {
            final ViewHolder viewHolder = getChildViewHolderInt(view);
            // Delete the entry into the reclamation pool
            if(viewHolder.isInvalid() && ! viewHolder.isRemoved() && ! mRecyclerView.mAdapter.hasStableIds()) { removeViewAt(index); recycler.recycleViewHolderInternal(viewHolder); }// Merge the detach table entry into the Scrap collection
            else{ detachViewAt(index); recycler.scrapView(view); mRecyclerView.mViewInfoStore.onViewDetached(viewHolder); }}}Copy the code

Depending on its state, the viewHolder is either added to the mAttachedScrap collection or stored in the recycling pool. Which recycleViewHolderInternal () in RecyclerView caching mechanism (recovery going?) Analysis. Continuing up the call chain:

public abstract static class LayoutManager {
         // Temporarily separate and reclaim the visible entries
        public void detachAndScrapAttachedViews(Recycler recycler) {
            final int childCount = getChildCount();
            // Iterate over all visible entries and reclaim them
            for (int i = childCount - 1; i >= 0; i--) {
                finalView v = getChildAt(i); scrapOrRecycleView(recycler, i, v); }}// Layout all child entries
        public void onLayoutChildren(Recycler recycler, State state) {...// Reclaim all entries before they are populateddetachAndScrapAttachedViews(recycler); .// Fill the entry
            fill(recycler, mLayoutState, state, false); . }}public class RecyclerView extends ViewGroup implements ScrollingView.NestedScrollingChild2 {
    RecyclerView The second step of the layout
    private void dispatchLayoutStep2(a) {... mLayout.onLayoutChildren(mRecycler, mState); . }}Copy the code
  • Entries are reclaimed before being filled in to the list one by onemAttachedScrap, the source of the recovery data isLayoutManagerChildren, andLayoutManagerChildren are entries that are visible or about to be visible on the screen.
  • In the comment, “temporarily separate and recycle the entries that are currently visible”. Since it is “temporarily recycle”, reuse will inevitably occur later. Reuse logic can be moved RecyclerView cache mechanism (how to reuse?
  • At this point it can be concluded that MathedScrap is used for recycling and reuse of on-screen visible entries

Empty content

Search globally for where mAttachedScrap is accessed, only one of which calls mAttachedScrap.clear():

public class RecyclerView {
    public final class Recycler {
        // Empty the scrap structure
        void clearScrap(a) {
            mAttachedScrap.clear();
            if(mChangedScrap ! =null) { mChangedScrap.clear(); }}}}Copy the code

Discard scrap () clears the list of scrap. And it will be LayoutManager. RemoveAndRecycleScrapInt () is called:

public abstract static class LayoutManager {
         // Quot; scrapped View; quot;
        void removeAndRecycleScrapInt(Recycler recycler) {
            final int scrapCount = recycler.getScrapCount();
            // Loop backward, recycler might be changed by removeDetachedView()
            // Iterate through the Scrap View to reset the ViewHolder state and reclaim it to the cache pool
            for (int i = scrapCount - 1; i >= 0; i--) {
                final View scrap = recycler.getScrapViewAt(i);
                final ViewHolder vh = getChildViewHolderInt(scrap);
                if (vh.shouldIgnore()) {
                    continue;
                }
                vh.setIsRecyclable(false);
                if (vh.isTmpDetached()) {
                    mRecyclerView.removeDetachedView(scrap, false);
                }
                if(mRecyclerView.mItemAnimator ! =null) {
                    mRecyclerView.mItemAnimator.endAnimation(vh);
                }
                vh.setIsRecyclable(true);
                recycler.quickRecycleScrapView(scrap);
            }
            // Clear the Scrap View collection
            recycler.clearScrap();
            if (scrapCount > 0) { mRecyclerView.invalidate(); }}}Copy the code

Up the call chain:

public class RecyclerView extends ViewGroup implements ScrollingView.NestedScrollingChild2 {
    RecyclerView The final step of the layout
    private void dispatchLayoutStep3(a) {... mLayout.removeAndRecycleScrapInt(mRecycler); . }Copy the code

Thus it can be concluded that the life cycle of mAttachedScrap starts from the RecyclerView layout and ends at the RecyclerView layout.

After analyzing the life cycle and purpose of Scrap, a new question arises: In what scenarios should you recycle and reuse on-screen entries? Limited to space reasons, reading the original code length knowledge | RecyclerView layout, the layout and scrap the cache made a detailed analysis of the relationship between.

conclusion

After the analysis of four articles, RecyclerVeiw four levels of cache are analyzed, summarized as follows:

  1. RecyclerThere are four levels for cachingViewHolderObjects whose priorities are in descending orderArrayList<ViewHolder> mAttachedScrap,ArrayList<ViewHolder> mCachedViews,ViewCacheExtension mViewCacheExtension,RecycledViewPool mRecyclerPool. If none of the four layer caches is hit, it is recreated and boundViewHolderobject

  2. Cache performance:

    The cache To recreate theViewHolder Rebind data
    mAttachedScrap false false
    mCachedViews false false
    mRecyclerPool false true
  3. Cache capacity:

    • mAttachedScrap: has no size limit, but contains a maximum of screen visible entries.
    • mCachedViews: The default size limit is 2. If it does not fit, it will be the first to enter according to the first-in, first-out principleViewHolderStore in the recycling pool to make room.
    • mRecyclerPool:ViewHolderAccording to theviewTypeStorage by category (PassedSparseArray), the same kindViewHolderStored in a default size of 5ArrayListIn the.
  4. Cache purpose:

    • mAttachedScrap: Recycles and reuses screen – visible entries during the layout.
    • mCachedViews: Is used to reclaim and reuse off-screen entries. It can only be used for entries in a specified location. It is similar to reclaim pool ready queue, that is, it is always reclaimed firstmCachedViewsWhen it doesn’t fit in, it will be the first in on the first-in, first-out principleViewHolderStored in the recycling pool.
    • mRecyclerPool: Is used to reclaim and reuse off-screen entries. It can only be used to specifyviewTypeThe table of items
  5. Cache structure:

    • mAttachedScrap:ArrayList<ViewHolder>
    • mCachedViews:ArrayList<ViewHolder>
    • mRecyclerPool:ViewHolderAccording to theviewTypeClassified storage inSparseArray<ScrapData>In the same kindViewHolderStored in theScrapDataIn theArrayListIn the

Recommended reading

RecyclerView

  1. RecyclerView caching mechanism | how to reuse table?

  2. What RecyclerView caching mechanism | recycling?

  3. RecyclerView caching mechanism | recycling where?

  4. RecyclerView caching mechanism | scrap the view of life cycle

  5. Read the source code long knowledge better RecyclerView | click listener

  6. Proxy mode application | every time for the new type RecyclerView is crazy

  7. RecyclerView table item child control click on the listener

  8. More efficient refresh RecyclerView | DiffUtil secondary packaging

  9. Change a thought, super simple RecyclerView preload

  10. RecyclerView animation principle | change the posture to see the source code (pre – layout)

  11. RecyclerView animation principle | pre – layout, post – the relationship between the layout and scrap the cache

  12. RecyclerView animation principle | how to store and use animation attribute values?

  13. RecyclerView list of interview questions | scroll, how the list items are filled or recycled?

  14. RecyclerView interview question | what item in the table below is recycled to the cache pool?

  15. RecyclerView performance optimization | to halve load time table item (a)

  16. RecyclerView performance optimization | to halve load time table item (2)

  17. RecyclerView performance optimization | to halve load time table item (3)

  18. RecyclerView rolling is how to achieve? (a) | unlock reading source new posture

  19. RecyclerView when rolling how to achieve? (2) | Fling

  20. RecyclerView Refreshes list data at notifyDataSetChanged() Why is it expensive?