RecyclerView與ListView 對比淺析:緩衝機制,

來源:互聯網
上載者:User

RecyclerView與ListView 對比淺析:緩衝機制,
一. 背景

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,導致必定會調用createViewfinal 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在使用上會更加方便,快捷。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.