RecyclerView與ListView 對比淺析:緩存機制

来源:https://www.cnblogs.com/ganchuanpu/archive/2018/01/10/8258459.html
-Advertisement-
Play Games

一. 背景 PS:相關知識:ListView與RecyclerView緩存機制原理大致相似,如下圖所示: 滑動過程中,離屏的ItemView即被回收至緩存,入屏的ItemView則會優先從緩存中獲取,只是ListView與RecyclerView的實現細節有差異.(這隻是緩存使用的其中一個場景,還有 ...


一. 背景

PS:相關知識:
ListView與RecyclerView緩存機制原理大致相似,如下圖所示:

滑動過程中,離屏的ItemView即被回收至緩存,入屏的ItemView則會優先從緩存中獲取,只是ListView與RecyclerView的實現細節有差異.(這隻是緩存使用的其中一個場景,還有如刷新等)

二. 正文

2.1 緩存機制對比

1. 層級不同:
RecyclerView比ListView多兩級緩存,支持多個離ItemView緩存,支持開發者自定義緩存處理邏輯,支持所有RecyclerView共用同一個RecyclerViewPool(緩存池)。

具體來說:
ListView(兩級緩存):

RecyclerView(四級緩存):

ListView和RecyclerView緩存機制基本一致:

1). mActiveViews和mAttachedScrap功能相似,意義在於快速重用屏幕上可見的列表項ItemView,而不需要重新createView和bindView;
2). mScrapView和mCachedViews + mReyclerViewPool功能相似,意義在於緩存離開屏幕的ItemView,目的是讓即將進入屏幕的ItemView重用.
3). RecyclerView的優勢在於a.mCacheViews的使用,可以做到屏幕外的列表項ItemView進入屏幕內時也無須bindView快速重用;b.mRecyclerPool可以供多個RecyclerView共同使用,在特定場景下,如viewpaper+多個列表頁下有優勢.客觀來說,RecyclerView在特定場景下對ListView的緩存機製做了補強和完善。

2. 緩存不同:

1). RecyclerView緩存RecyclerView.ViewHolder,抽象可理解為:
View + ViewHolder(避免每次createView時調用findViewById) + flag(標識狀態);
2). ListView緩存View。

緩存不同,二者在緩存的使用上也略有差別,具體來說:
ListView獲取緩存的流程:

RecyclerView獲取緩存的流程:

1). RecyclerView中mCacheViews(屏幕外)獲取緩存時,是通過匹配pos獲取目標位置的緩存,這樣做的好處是,當數據源數據不變的情況下,無須重新bindView:

而同樣是離屏緩存,ListView從mScrapViews根據pos獲取相應的緩存,但是並沒有直接使用,而是重新getView(即必定會重新bindView),相關代碼如下:

//AbsListView源碼:line2345
//通過匹配pos從mScrapView中獲取緩存
final View scrapView = mRecycler.getScrapView(position);
//無論是否成功都直接調用getView,導致必定會調用createView
final View child = mAdapter.getView(position, scrapView, this);
if (scrapView != null) {
    if (child != scrapView) {
        mRecycler.addScrapView(scrapView, position);
    } else {
                ...
    }
}

2). ListView中通過pos獲取的是view,即pos-->view;
RecyclerView中通過pos獲取的是viewholder,即pos --> (view,viewHolder,flag);
從流程圖中可以看出,標誌flag的作用是判斷view是否需要重新bindView,這也是RecyclerView實現局部刷新的一個核心。

2.2 局部刷新

由上文可知,RecyclerView的緩存機制確實更加完善,但還不算質的變化,RecyclerView更大的亮點在於提供了局部刷新的介面,通過局部刷新,就能避免調用許多無用的bindView。

(RecyclerView和ListView添加,移除Item效果對比)

結合RecyclerView的緩存機制,看看局部刷新是如何實現的:
以RecyclerView中notifyItemRemoved(1)為例,最終會調用requestLayout(),使整個RecyclerView重新繪製,過程為:
onMeasure()-->onLayout()-->onDraw()

其中,onLayout()為重點,分為三步:
dispathLayoutStep1():記錄RecyclerView刷新前列表項ItemView的各種信息,如Top,Left,Bottom,Right,用於動畫的相關計算;
dispathLayoutStep2():真正測量佈局大小,位置,核心函數為layoutChildren();
dispathLayoutStep3():計算佈局前後各個ItemView的狀態,如Remove,Add,Move,Update等,如有必要執行相應的動畫.

其中,layoutChildren()流程圖:

當調用notifyItemRemoved時,會對屏幕內ItemView做預處理,修改ItemView相應的pos以及flag(流程圖中紅色部分):

當調用fill()中RecyclerView.getViewForPosition(pos)時,RecyclerView通過對pos和flag的預處理,使得bindview只調用一次.

需要指出,ListView和RecyclerView最大的區別在於數據源改變時的緩存的處理邏輯,ListView是"一鍋端",將所有的mActiveViews都移入了二級緩存mScrapViews,而RecyclerView則是更加靈活地對每個View修改標誌位,區分是否重新bindView。

三.結論

1、在一些場景下,如界面初始化,滑動等,ListView和RecyclerView都能很好地工作,兩者並沒有很大的差異:

文章的開頭便拋出了這樣一個問題,微信Android客戶端卡券模塊,大部分UI都是以列表頁的形式展示,實現方式為ListView,是否有必要將其替換成RecyclerView呢?

答案是否定的,從性能上看,RecyclerView並沒有帶來顯著的提升,不需要頻繁更新,暫不支持用動畫,意味著RecyclerView優勢也不太明顯,沒有太大的吸引力,ListView已經能很好地滿足業務需求。

2、數據源頻繁更新的場景,如彈幕:http://www.jianshu.com/p/2232a63442d6 等RecyclerView的優勢會非常明顯;

進一步來講,結論是:
列表頁展示界面,需要支持動畫,或者頻繁更新,局部刷新,建議使用RecyclerView,更加強大完善,易擴展;其它情況(如微信卡包列表頁)兩者都OK,但ListView在使用上會更加方便,快捷。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 資料庫是網路應用的基礎,良好的表結構設計,對整個應用起著至關重要的作用。 資料庫設計的步驟: 1.需求分析:數據是什麼,有哪些屬性,數據和屬性的特點 2.邏輯設計:使用ER圖對資料庫進行邏輯建模 3.物理設計:選擇資料庫系統,並對邏輯設計進行轉化 4.維護優化:追加,分拆等 實例演示(電子商務網站) ...
  • 概述 擴展存儲過程是 SQL Server 實例可以動態載入和運行的 DLL。擴展存儲過程是使用 SQL Server 擴展存儲過程 API 編寫的,可直接在 SQL Server 實例的地址空間中運行。擴展存儲過程可能會產生記憶體泄漏或其他降低伺服器的性能及可靠性的問題。固定伺服器角色 sysadm ...
  • 資料庫SQL三種迴圈語句(For、While、Loop) ...
  • 學完這本書,就把精華都寫出了 ...
  • NO是常開(NORMAL OPEN),就是通常即未通電狀態下,是斷開的,通電後在電磁線圈的作用下(吸合)處於閉合狀態。NC是常閉(NORMAL CLOSE),就是通常即未通電狀態下,是閉合的,通電後在電磁線圈的作用下(吸合)處於斷開狀態。 指接觸器、繼電器等電氣開關元件輔助觸點在常態下(未通電時)的 ...
  • 背景 iPhone X 劉海機於9月13日發佈,給科技小春晚帶來一波高潮。作為開發人員卻多出來一份憂慮,iPhone X 怎麼適配?我們 App 的腦袋會不會也長一劉海出來?Tabbar 會不會被圓角?先來看一下美團 App 的表現: 圖 1.1 啟動時的 App 表現 圖 1.2 下拉刷新之後的表 ...
  • iOS11對WKWebView的功能進一步完善,新增如下功能: ...
  • 今天研究了一下在Xcode中創建多個工程,達到模塊化的目的的同時,實現多個相似項目的協同開發,最主要的是可以實現多工程連編。項目的效果如下: 接下來創建一個這樣的項目,以及他們之間的通信 1.建一個文件夾MyProject(這是本人採用的文件夾) 2.在MyProject文件夾下創建一個工作空間My ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...