日韩性视频-久久久蜜桃-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 复用解析》的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 日本不卡一区 | 美女操操操 | 国产午夜片 | 日日干干 | 国产freexxxx性播放麻豆 | 美女张开腿让男人操 | 久久免费视频3 | 999国内精品永久免费视频 | 91综合网| 国产青草视频在线观看 | 日本免费网站视频 | www.久久| 亚洲午夜精品视频 | 久久e热| 国产sm网站 | 欧美又大又硬又粗bbbbb | 成年人免费在线视频 | 欧美小视频在线 | 国产精品国产自产拍高清av | 国产一区二区av在线 | 日韩一区二区三区三四区视频在线观看 | 精品国产91久久久久久久妲己 | 黄色特级毛片 | 久久综合九色综合欧美狠狠 | 中文字幕av解说 | 午夜影院一区 | 中文字幕在线网站 | 欧美日皮视频 | 91禁看片 | 超爽视频| 伊人网成人网 | 日韩乱码人妻无码中文字幕久久 | 欧美福利在线 | 日p免费视频 | julia一区二区三区中文字幕 | 中文字幕av在线免费 | 中文字幕2区 | 小黄网站在线观看 | 观看av在线 | 精品视频一区二区三区四区五区 | 男女爽爽爽 | 国产欧美一区二区三区四区 | 久久精品男人 | 亚洲精品视频三区 | 久久一区二区精品 | 午夜电影福利网 | 精品国产福利 | 中文在线资源天堂 | 爱爱激情网 | 国产精品久久中文字幕 | 精品中文一区二区三区 | 91激情影院 | 久草网在线观看 | 爱草在线视频 | 国产精品成人久久久久 | 蜜臀va| 成人一级大片 | 亚洲精品福利网站 | 午夜精品在线播放 | 免费的av网址 | 亚洲成人毛片 | 明日花绮罗高潮无打码 | 国产精品情侣呻吟对白视频 | 黄网在线观看免费 | 日本大尺度激情做爰hd | 日韩福利一区二区三区 | av福利在线免费观看 | 国产精品国产三级国产a | 手机看片福利永久 | 国产看片网站 | 黄色在线观看av | 欧美日韩一区二区三区在线电影 | 精品亚洲天堂 | 捆绑调教视频网站 | 国产一卡二卡在线播放 | 椎名空在线播放 | 就操在线| 亚洲av成人片色在线观看高潮 | 日韩女同强女同hd | 欧美精品免费播放 | 国产a国产片 | 三上悠亚在线一区 | www亚洲成人 | 国产亚洲一区二区在线 | 久久夜色精品亚洲 | 成人h视频在线 | 国产成人超碰人人澡人人澡 | 精品成人中文无码专区 | 少妇把腿扒开让我舔18 | 在线观看色网 | 成人精品视频一区二区 | jizz久久| 国产精品网站在线 | 日日拍拍 | 国产精品一二三区在线观看 | 丝袜美腿亚洲综合 | 亚洲aⅴ在线 | a视频免费看| 亚洲欧美福利 |