RecyclerView + DiffUtil 使用預(yù)研

背景:RecyclerView 使用notifyDataSetChanged 會導(dǎo)致圖片閃爍

具體原因可參看:RecyclerView 體驗優(yōu)化及入坑總結(jié)? 的入坑篇第二個問題

一、RecyclerView 局部刷新不好用

? ? ? RecyclerView 除了配置動畫、布局等方便外,相比ListView ,提供了不少數(shù)據(jù)刷新方式,除了常見的notifyDataSetChanged() 全局刷新外,還提供了很多局部刷新方式,列舉如下:

圖1? RecyclerView Adapter 對應(yīng)刷新方式

? ? ? ? 上述局部刷新方式,看似好用(插入、更新、移動、刪除),但實際不太好用,甚至基本無用。不好用的原因在于,不知何時去選擇刷新方式 ,因而還是一股腦的使用notifyDataSetChanged() ,除此之外 使用較多的場景 :頁面加載更多 ,使用notifyItemRangeChanged(int ,int),替他刷新方式根本沒有使用過。

? ? ? ?可能正因如此,Google 在?Support-v7:24:2.0 提供了DiffUtils 類,讓我們正真意義上使用RecyclerView 的局部刷新。

二 、DiffUtil 介紹 及使用

? ? ? ? DiffUtil是 Support-v7:24:2.0 中,中更新的工具類,主要是為了配合RecyclerView使用,通過比對新、舊兩個數(shù)據(jù)集的差異,生成舊數(shù)據(jù)到新數(shù)據(jù)的最小變動,然后對有變動的數(shù)據(jù)項,進行局部刷新。

? ?DiffUtil 核心內(nèi)容 :

(1)DiffUtil.Callback??

DiffUtil.Callback? :具體用于限定數(shù)據(jù)集比對規(guī)則 ,內(nèi)部主要有如下5個比較方法:

圖 2 DiffUtil.Callback?

?1)getOldListSize():舊數(shù)據(jù)集的長度;

?2)getNewListSize():新數(shù)據(jù)集的長度

?3)areItemsTheSame():判斷是否是同一個item;

?4)areContentsTheSame():如果item相同,此方法用于判斷是否同一個 Item 的內(nèi)容也相同;

圖3? areContentsTheSame()

?5)getChangePayload() :如果item相同,內(nèi)容不同,用 payLoad 記錄這個 ViewHolder 中,具體需要更新那個View

? ? 從圖2知 ,getChangePayload() 默認(rèn)返回 null ,即整個item 全部刷新。

圖4? getChangePayload()

? ? 一般在getChangePayload()方法中調(diào)用super.getChangePayload() 即可,不做精細(xì)化刷新。

? ? ?如果一個item 非常復(fù)雜,存在里面某個View 數(shù)據(jù)刷新,可以利用payLoad參數(shù)來實現(xiàn),對應(yīng)修改點 在 onBindViewHolder(HelloViewHolder holder, int position ) 的基礎(chǔ)上實現(xiàn)帶參的?onBindViewHolder ,同時在getChangedPayLoad()對應(yīng)實現(xiàn)。

從上面分析可知:areItemsTheSame()、areContentsTheSame()、getChangePayload()?分別代表了不同量級的刷新。

(2)DiffUtil.DiffResult

DiffUtil.DiffResult : 比對數(shù)據(jù)集之后,返回的差異結(jié)果 ,通過DiffUtil.calculateDiff(diffCallback)(當(dāng)數(shù)據(jù)量較大時,建議放在子線程中調(diào)用)得到。

DiffUtil.DiffResult::dispatchUpdatesTo() 根據(jù)diff 數(shù)據(jù)結(jié)果,選擇刷新方式。

圖5 DiffUtil.DiffResult::dispatchUpdatesTo()


?總結(jié):使用起來比較簡單 ,1)實現(xiàn)DiffUtil.Callback? ?接口 ;2)新老數(shù)據(jù)集通過DiffUtil.calculateDiff 計算得到DiffUtil.DiffResult? ;3)DiffUtil.DiffResult::dispatchUpdatesTo()? 刷新數(shù)據(jù)。

三、項目使用DiffUtil遇到的問題

? ? ?在第二節(jié)中 ,已經(jīng)基本介紹了DiffUtil 的使用,本節(jié)以精選頁、書城等頁面為例(忽略代碼中邊界值處理)說明 ,在使用過程中遇到的一些問題:

(1)item 判斷 唯一性

? ? ? ?目前 ,setData ()? 數(shù)據(jù)類型為? ArrayList<RowData>? (多ViewType類型)如下 ,對于item 來說 ,缺少唯一性判斷屬性。

圖6 RowData()

? ? ? ?目前,使用mDisplayStyle 和id 來判斷 item 是否一致。 如果item一致,則會進一步判斷 item 內(nèi)容是否一致(areContentsTheSame);如果item 不一致,則item 全部刷新。

圖7 areItemsTheSame()

(2)?areContentsTheSame() 判斷過于麻煩?

? ?由于RowData 內(nèi) 核心數(shù)據(jù)是mData (Object型),無法直接比較 實現(xiàn)equals ,只能在?areContentsTheSame() 內(nèi),手動實現(xiàn)每種ViewType 數(shù)據(jù)的equals (對象是jce協(xié)議,只能手動實現(xiàn))。

手動實現(xiàn)的問題在于:1)jce協(xié)議新增字段,這里需要補充 ;2)新增ViewType 數(shù)據(jù)需要在這里補充;3)對應(yīng)adapter 與這個callBack 關(guān)聯(lián)性不大,易漏

上述三個問題,可能增加一定的維護成本

圖8? areContentsTheSame

RowDataDiffCallback() 整體實現(xiàn)? :

圖9? RowDataDiffCallback()

(3)VM 初始化 設(shè)置pullToRefreshRecycleView.setEnableLoadMore(true),導(dǎo)致頁面滑到最下面

? ? ?目前,猜測 是加載更多模塊焦點導(dǎo)致 (猜測未找出原因)

分析一下該問題 :pullToRefreshRecycleView.setEnableLoadMore(true) 設(shè)置本不應(yīng)該在VM初始化時,設(shè)置,應(yīng)該根據(jù)回包數(shù)據(jù) 的hasMore 來設(shè)置 。

直接將pullToRefreshRecycleView.setEnableLoadMore(true)? 改成在回包時,調(diào)用?pullToRefreshRecycleView.setEnableLoadMore(hasMore) 上述問題解決


? ? ? 上述3個問題,是我在使用diffutil中遇到的問題,在項目中可以使用,大家有空看看,還有什么疑問或改正意見。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,048評論 25 709
  • 這篇文章分三個部分,簡單跟大家講一下 RecyclerView 的常用方法與奇葩用法;工作原理與ListView比...
    LucasAdam閱讀 4,704評論 0 27
  • 步驟1.viewDidLoad{}方法中設(shè)置監(jiān)聽 步驟2.在.m中添加此方法,此時已經(jīng)設(shè)置結(jié)束編輯時(收起鍵盤時頁...
    PZcoder閱讀 396評論 0 0
  • 滅痘可用棉簽取適量茶樹精油,點在痘痘上,堅持1到3天,發(fā)紅的痘痘就會變得干癟。 新生痘印用薰衣草點涂局部,可消炎平...
    茶壺家閱讀 282評論 0 0
  • 最美的黃昏應(yīng)該是什么樣子的? 如果是戀人,任何地方的黃昏都最美。廢話了。林蔭小道,山間地頭,蔚藍海岸,街心公園,人...
    田曉隱閱讀 2,437評論 0 3

友情鏈接更多精彩內(nèi)容