RecycleView與ListView的區別以及RecycleView緩存機制總結

RV和LV的區別

LV:
  1. 繼承並重寫BaseAdapter類,佈局效果單一
  2. 自定義ViewHolder和convertView的複用優化
  3. 可以通過addHeaderView()和addFooterView()添加下拉刷新的頭部view與上拉加載更多的底部view,且不會影響Adapter的編寫
  4. 在刷新條目數據時通常使用notifyDataSetChanged()方法這種刷新數據是全局刷新的方式,每個item的數據都會重新加載一遍,會消耗更多的資源,如果要實現局部刷新,則需要在Adapter中自定義方法,調用getFirstVisiblePosition()獲取到對應item的position,然後調用getView()方法來刷新這個item的數據
  5. 沒有動畫效果的實現,需要自己在Adapter中自己實現
  6. 有現成的點擊方法->onItemClickListener()->onItemLongClickListener()-onItemSelectedListener()
  7. 沒有嵌套滾動機制
RV:
  1. 繼承重寫RecyclerView.Adapter類,覆寫onCreateViewHolder方法和onBindViewHolder方法,實現自己的ViewHolder類,繼承重寫RecyclerView.Holder,通過設置LayoutManager以及layout的佈局效果:線性,表格,瀑布流或者自定義LayoutManager
  2. 複用優化有四級緩存,無需自定義,如果不滿足於默認設置,可以手動設置pool等緩存優化
  3. 沒有添加HeaderView和FooterView的方法,需要在Adapter中根據getItemViewType()自己實現,但是這樣會導致實際position的值產生偏差
  4. RecyclerView可以使用全局刷新和局部刷新->notifyItemChanged(int position)
  5. 有已經封裝好的簡單動畫->notifyItemChange(),notifyDataInserted(),notifyItemMoved等,如需自定義動畫,需要實現動畫接口RecyclerView.ItemAnimator類,然後調用RecyclerView.setItemAnimator()設置動畫效果
  6. 沒有現成的點擊事件,需要自己手動實現
  7. 實現了嵌套滑動機制.Android的事件分發機制中,Touch事件在進行分發時,有父View向子View傳遞,一旦子View消費了此事件則父View不在接受後續的分發處理,處理交由子View進行;但是嵌套滾動機制通過實現NestedScrollingChild()和NestedScrollingParent()兩個接口可以讓子View和父View同時處理此Touch事件

RV的四級緩存

  1. Scrap:一級緩存,緩存了屏幕內顯示的所有viewholder,在這一級緩存的viewholder可以有效的避免重複的create和bind,緩存的時機是onLayout,並且用完後立即清空;在列表滑出新的item時,LayoutManager會先把屏幕中的所有的viewholder廢棄掉,放入mAttachedView中,然後再根據flag重新佈局每個itemview,並清空ScrapView
    1. mAttachedScrap,ArrayList,用於存放當前屏幕中的viewholder;用於存放flag爲失效,移除的viewholder和完全沒有改變的viewholder,有多少存多少;從這裏獲得的viewholder不需要走onBindViewHolder()方法
    2. mChangedScrap,ArrayList,用於存放數據被更新後的viewholder,也就是flag爲更新的viewholder;這些viewholder需要被adapter重新綁定
  2. mCachedViwe,默認大小爲2,用於存放預讀取的viewholder,只有當所需的viewholder和position相同並且flag爲有效時才獲取此viewhodler,由於已經判斷了viewholder是有效的,所以就不需要進行bind操作了;由於mCacheedView是有大小限制的,因此,如果超過了默認緩存大小,則會移除mCachedViwe的第一個viewholder,然後把需要添加的viewholder添加進入mCachedViwe,被移除的和不能加入的viewholder則會加入到mRecyclerViewPool中
  3. ViewCacheExtension,自定義緩存,通常用不到
  4. RecyclerViewPool,緩存池,根據viewType來緩存viewHolder,每個viewType可緩存的數量爲5,可以動態的改變

RV的flag種類:失效,廢棄,分離,移除,綁定,更新

緩存流程

RV複用的流程就是獲取viewholder的流程;獲取viewholder從Recycler的getViewForPosition開始

  1. 在mAttachedScrap或者mChangedScrap中根據position和flag查找到對應viewholder,獲取並返回viewholder,根據flag決定viewhodler是否重新綁定
  2. 如果上一步沒有獲取到viewhodler,則從mCacheViews中匹配position獲取viewholder緩存,獲取並返回viewholder
  3. 如果上一步沒有獲取到viewhodler,則從ViewCacheExtension中獲取viewholder,獲取並返回viewholder
  4. 如果上一步沒有獲取到viewhodler,則從RecyclerViewPool中根據itemtype獲取緩存的viewhodler,清除獲取的viewhodler的所有標記位置,確保viewhodler能重新被adapter綁定
  5. 如果上一步沒有獲取到viewhodler,則走adapter的CreateViewHolder方法,創建一個新的viewholder,並經過adapter的bindViewHolder綁定改viewholder

源碼分析乾貨:
https://www.jianshu.com/p/c52b947fe064
https://www.jianshu.com/p/efe81969f69d
https://juejin.im/post/5b79a0b851882542b13d204b

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章