【騰訊Bugly乾貨分享】Android ListView與RecyclerView對比淺析--緩存機制

本文來自於騰訊bugly開發者社區,非經做者贊成,請勿轉載,原文地址:http://dev.qq.com/topic/5811d...java

做者:黃寧源android

一,背景

RecyclerView是谷歌官方出的一個用於大量數據展現的新控件,能夠用來代替傳統的ListView,更增強大和靈活。緩存

最近,本身負責的業務,也遇到這樣的一個問題,關因而否要將ListView替換爲RecyclerView?微信

秉承着實事求是的做風,弄清楚RecyclerView是否有足夠的吸引力替換掉ListView,我從性能這一角度出發,研究RecyclerView和ListView兩者的緩存機制,並獲得了一些較有益的"結論",待我慢慢道來。函數

同時也但願能經過本文,讓你們快速瞭解RecyclerView與ListView在緩存機制上的一些區別,在使用上也更加駕輕就熟吧。工具

PS:相關知識:
ListView與RecyclerView緩存機制原理大體類似,以下圖所示:佈局

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

PPS:本文不貼出詳細代碼,結合源碼食用更佳!學習

二. 正文

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()爲重點,分爲三步:

  1. dispathLayoutStep1():記錄RecyclerView刷新前列表項ItemView的各類信息,如Top,Left,Bottom,Right,用於動畫的相關計算;

  2. dispathLayoutStep2():真正測量佈局大小,位置,核心函數爲layoutChildren();

  3. 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已經能很好地知足業務需求。

  1. 數據源頻繁更新的場景,如彈幕:http://www.jianshu.com/p/2232...等RecyclerView的優點會很是明顯;

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

Ps:僅從一個角度作了對比,盲人摸象,有誤跪求指正。

四.參考資料

1. ListView

  1. Android-23源碼

  2. Android ListView工做原理解析,帶你從源碼的角度完全理解:http://blog.csdn.net/guolin_b...

  3. Android本身動手寫ListView學習其原理:http://blog.csdn.net/androidd...

2. RecyclerView

  1. RecyclerView-v7-23.4.0源碼

  2. RecyclerView剖析:http://blog.csdn.net/qq_23012...

  3. RecyclerView剖析:http://blog.csdn.net/qq_23012...


更多精彩內容歡迎關注bugly的微信公衆帳號:

騰訊 Bugly是一款專爲移動開發者打造的質量監控工具,幫助開發者快速,便捷的定位線上應用崩潰的狀況以及解決方案。智能合併功能幫助開發同窗把天天上報的數千條 Crash 根據根因合併分類,每日日報會列出影響用戶數最多的崩潰,精準定位功能幫助開發同窗定位到出問題的代碼行,實時上報能夠在發佈後快速的瞭解應用的質量狀況,適配最新的 iOS, Android 官方操做系統,鵝廠的工程師都在使用,快來加入咱們吧!

相關文章
相關標籤/搜索