日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小葵花妈妈课堂开课了《RecyclerView 复用解析》

發布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小葵花妈妈课堂开课了《RecyclerView 复用解析》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最新項目遇到一個問題,就是RecycleView的itemview會頻繁拉取圖片,同一時間多次拉取同一張照片。
初探,是因為該場景notifyDataSetChanged()過于頻繁,一秒鐘會調用5次左右,
導致ViewHolder沒有復用,也不是沒有復用而是復用的并沒有像理想中的樣式。

notify

  • notifyDataSetChanged
  • mObservable.notifyChanged()
  • mObservers.get(i).onChanged();
  • setDataSetChangedAfterLayout();
    4.1.1 markKnownViewsInvalid
    //1 Mark all known views as invalid,僅標記可見的布局為ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID
    //2 mAdapter.hasStableIds() true -> mCachedViews 標記 ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID
    //3 mAdapter.hasStableIds() false -> addViewHolderToRecycledViewPool ->getRecycledViewPool().putRecycledView(holder); AND mCachedViews.clear();
    // we cannot re-use cached views in this case. Recycle them all
    4.1.2 markItemDecorInsetsDirty
    //child.getLayoutParams()).mInsetsDirty = true;
    //mCachedViews layoutParams.mInsetsDirty = true;
  • requestLayout();
  • 回收邏輯

  • void onLayout(boolean changed, int l, int t, int r, int b)
  • dispatchLayout()
  • void dispatchLayoutStep2()
  • void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)
  • detachAndScrapAttachedViews(recycler); //先回收,在fill,也就是后去查找可以復用的holder。僅處理children holder
  • scrapOrRecycleView(recycler, i, v);
    6.1 viewHolder.isInvalid() && !viewHolder.isRemoved() && !mRecyclerView.mAdapter.hasStableIds() -->
    6.1.1 true recycler.recycleViewHolderInternal(viewHolder);
    addViewHolderToRecycledViewPool(holder, true); //最終放入getRecycledViewPool()
    6.1.2 false scrapView(View view)
    holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID) || !holder.isUpdated() || canReuseUpdatedViewHolder(holder) -->
    6.1.2.1 true mAttachedScrap.add(holder);
    6.1.2.2 false mChangedScrap.add(holder);
    總結:如果Holder無效最終放入getRecycledViewPool,否則mAttachedScrap
  • 回收另外一個分支

  • onLayout
  • dispatchLayout
  • dispatchLayoutStep3
  • removeAndRecycleScrapInt //僅處理mAttachedScrap所緩存Holder
    vh.setIsRecyclable(true);
  • recycler.quickRecycleScrapView(scrap);
  • recycleViewHolderInternal(ViewHolder holder)
    forceRecycle || holder.isRecyclable() 成立
    (mViewCacheMax > 0 && !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID | ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) 不成立,包含ViewHolder.FLAG_INVALID
  • addViewHolderToRecycledViewPool(ViewHolder holder, boolean dispatchRecycled)
  • getRecycledViewPool().putRecycledView(holder); 最終放到了getRecycledViewPool中。
  • 查找可復用Holder過程

  • void onLayout(boolean changed, int l, int t, int r, int b)
  • dispatchLayout()
  • void dispatchLayoutStep2()
  • void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)
  • fill(RecyclerView.Recycler recycler, LayoutState layoutState,
    RecyclerView.State state, boolean stopOnFocusable)
  • layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
    LayoutState layoutState, LayoutChunkResult result)
  • LinerLayout.next
  • getViewForPosition
  • tryGetViewHolderForPositionByDeadline
    9.1 isPreLayout() --> getChangedScrapViewForPosition(int position) //如果是pre-layout,會從mChangedScrap獲取復用
    9.2 getScrapOrHiddenOrCachedHolderForPosition(position, dryRun)
    9.2.1 mAttachedScrap 首先從該處獲取,
    9.2.2 mChildHelper.findHiddenNonRemovedView(position) 拿到隱藏的ViewHolder
    9.2.3 mCachedViews //Search in our first-level recycled view cache. 最后從一級緩存獲取
    // invalid view holders may be in cache if adapter has stable ids as they can be
    // retrieved via getScrapOrCachedViewForId
    // 通過原廠注釋可以知道,has stable才可以使用mCachedViews緩存。在回收處也可以看出。
    9.2.4 mAdapter.hasStableIds() --> getScrapOrCachedViewForId() //仍然需要hasStableIds
    // 首先mAttachedScrap
    // 之后mCachedViews
    9.3 mViewCacheExtension //外部擴展
    9.4 getRecycledViewPool().getRecycledView(type) //此處查到holder被resetInternal,即需要重新bind
    9.5 mAdapter.createViewHolder(RecyclerView.this, type); //最后,create
  • bind過程

  • tryGetViewHolderForPositionByDeadline(int position,
    boolean dryRun, long deadlineNs)
  • tryBindViewHolderByDeadline
  • mAdapter.bindViewHolder(holder, offsetPosition);
  • 至此RecyclerView的復用機制已經差不多了。至此也看到了我的問題也出現了答案的線索。
    因為是notifyDataSetChanged出發的刷新,會將所有ViewHolder標記為FLAG_INVALID。
    在回收ViewHolder時,會放入getRecycledViewPool中。
    RecycledViewPool官方注釋

    RecycledViewPool lets you share Views between multiple RecyclerViews.
    If you want to recycle views across RecyclerViews, create an instance of RecycledViewPool
    and use {@link RecyclerView#setRecycledViewPool(RecycledViewPool)}.
    RecyclerView automatically creates a pool for itself if you don’t provide one.

    作用為多個RecyclerViews之間復用ViewHolder。
    可以通過setRecycledViewPool進行設置。
    SparseArray mScrap = new SparseArray<>(); 用來存儲不同類型的ViewHolder

    static class ScrapData {ArrayList<ViewHolder> mScrapHeap = new ArrayList<>();int mMaxScrap = DEFAULT_MAX_SCRAP;long mCreateRunningAverageNs = 0;long mBindRunningAverageNs = 0; }

    默認mMaxScrap大小為5個

    private static final int DEFAULT_MAX_SCRAP = 5;

    也就是做多存儲5個。我的項目正好有6個Item顯示,就導致只能存儲 1,2,3,4,5 而0沒有進行存儲
    onBind的時候就會出現0 - 綁定 1,1 綁定2… 的問題。

    解決辦法為通過
    new一個RecyclerView.RecycledViewPool, 并設置recycledViewPool.setMaxRecycledViews(0, 6);
    第一個參數viewType,我這里僅有一種type,所以就寫0
    最終通過mRecycleList.setRecycledViewPool(recycledViewPool); 設置RecycledViewPool。
    至此大工告成。

    RecyclerView源碼有1w多行。剛看的時候無從下手,向其他博主所說的見森林而不見樹木。
    我就是從notifyDataSetChanged 和 onBindViewHolder入手,查找上下邏輯從而追蹤定位問題。

    總結

    以上是生活随笔為你收集整理的小葵花妈妈课堂开课了《RecyclerView 复用解析》的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 奇米网在线观看 | 久草免费在线视频观看 | 性欧美大战久久久久久久免费观看 | 在线观看免费人成视频 | 999国产视频 | 中文字幕精品在线视频 | 欧美日韩亚洲精品一区二区 | 国产一级做a爰片久久毛片男男 | 男人插女人网站 | 日韩成人欧美 | 小柔的裸露日记h | 日批免费观看视频 | 奇米四色777 | 国产福利三区 | 伊人久久综合 | 久久综合色鬼 | 伊人操| 久国产精品 | 先锋影音资源av | 观看av免费 | 四虎色播| 一级片少妇 | 午夜日韩电影 | 免费在线播放黄色片 | 精品欧美国产 | 日本另类视频 | 在线观看自拍 | 国产农村妇女精品一区 | 亚洲免费影视 | 中文字幕一区二区三区又粗 | 亚洲中文一区二区三区 | 欧美高清hd | 欧美久久精品一级黑人c片 1000部多毛熟女毛茸茸 | 午夜视频大全 | 九九热超碰| 日本成人一区二区三区 | 人妻丝袜一区二区三区 | 亚洲午夜久久久久 | 国产精品xxxxx | 亚洲综合成人在线 | 女人裸体无遮挡 | 久久精品一区二区在线观看 | 免费看欧美片 | 好男人在线视频www 亚洲福利国产 | 亚洲综合久 | 校园伸入裙底揉捏1v1h | 福利在线视频导航 | 91碰在线视频 | 成人亚洲区 | 黄色片链接 | 色综合久久中文字幕无码 | 小视频国产| 欧美wwwxxxx| 欧美 另类 交 | 青青草婷婷 | 日韩视频一区 | 国产精品电影一区二区三区 | 毛片自拍| 自宅警备员在线观看 | 永久免费视频网站直接看 | 蜜臀尤物一区二区三区直播 | 粗大黑人巨茎大战欧美成人免费看 | 精品日本一区二区三区 | 在线不卡一区 | 国产一区二区三区四 | 国产欧美精品aaaaaa片 | 天狂传说之巴啦啦小魔仙 | 男女视频一区 | 中文字幕激情视频 | 成人激情小视频 | 欧美视频一二三 | 免费激情网址 | 青青视频网 | 尤物在线视频观看 | 91在线日韩 | 欧美一区二区三区色 | 就去色av| 一路向西在线看 | 亚洲人成人一区二区在线观看 | 色骚综合 | 国产精品美女久久久久 | 国产一级做a爰片在线看免费 | 亚洲国产成人精品久久久 | 91麻豆一区二区三区 | 深爱五月激情网 | 色图一区| 非洲黄色一级片 | 午夜影视在线观看 | 成人黄色三级视频 | 日韩av中文在线 | 亚洲精品国产一区二区 | 91视频在线网站 | 日韩欧美性视频 | 国模吧无码一区二区三区 | 日韩美女国产精品 | 欧美人与zoxxxx另类 | 免费精品一区 | 精品久久久久久中文字幕 | 久青草视频 |