Recyclerview多種場景下的優(yōu)化

前言

因為APP設(shè)計的原因,Recyclerview是我在Android中最常用的組件灾馒,我們公司的APP幾乎每一個頁面都會包含至少一個Recyclerview,本篇文章主要介紹一些我個人在工作中總結(jié)、收集的recyclerview優(yōu)化經(jīng)驗蕴掏。

正文

1.不要在onBindViewHolder中設(shè)置點擊事件和耗時操作

Recyclerview的onBindViewHoler主要負責(zé)將數(shù)據(jù)與holder綁定蹬挤,它在列表滑動時會不停的被調(diào)用缚窿。如果在onBindViewHolder中設(shè)定監(jiān)聽操作,會導(dǎo)致已經(jīng)的綁定點擊事件的view焰扳,被重復(fù)綁定監(jiān)聽操作倦零。

點擊事件的監(jiān)聽可以在onCreateViewHolder中設(shè)定。一些會創(chuàng)建新對象的操作吨悍,也需要根據(jù)實際情況考慮從onBindViewHolder中遷移到onCreateViewHolder扫茅。

注意: onBindViewHolder運行在UI線程中,如果進行了耗時操作育瓜,會導(dǎo)致頁面卡頓葫隙。并且onBindViewHolder中只應(yīng)該進行數(shù)據(jù)的綁定,而不應(yīng)該進行數(shù)據(jù)的處理和計算等操作躏仇。

2.Recyclerview嵌套Recyclerview的優(yōu)化

Recyclerview嵌套Recyclerview最經(jīng)典的運用就是恋脚,一個縱向滑動的列表內(nèi)部的每個item是一個可以橫向滑動的Recyclerview腺办,比如說GooglePlay。


Google play 截圖

這種情況可以使用LinearLayoutManager.setInitialPrefetchItemCount()設(shè)定
橫向列表初次顯示時可見item的個數(shù)糟描。如果橫向滑動的View中數(shù)據(jù)量很少怀喉,并且不需要橫向刷新時,也可以考慮使用HorizontalScrollView實現(xiàn)船响。

關(guān)于這個API的官方文檔翻譯如下:

  • 設(shè)置collectInitialPrefetchPositions(int躬拢,LayoutPrefetchRegistry)中要預(yù)取的項目數(shù),它定義當此LayoutManager的RecyclerView嵌套在另一個RecyclerView中時應(yīng)預(yù)取多少內(nèi)部項目灿意。

  • 將此值設(shè)置為此內(nèi)部LayoutManager首次滾動到視口時將顯示的項目數(shù)估灿。 RecyclerView將嘗試預(yù)取該數(shù)量的項目,并提前將這些Item初始化缤剧,避免因內(nèi)部RecyclerView滾動到視圖(viewport)中變得混亂馅袁。

  • 舉個例子,水平滾動的RecyclerViews內(nèi)部嵌套垂直滾動的RecyclerView荒辕。行中始終有4個項目可見(如果沒有對齊汗销,則是5個)。為每個內(nèi)部的RecyclerView的LinearLayoutManager設(shè)定setInitialPrefetchItemCount=4抵窒,這將使RecyclerView的預(yù)取功能能夠在屏幕上滾動之前弛针,提前為一行中的4個視圖完成創(chuàng)建/綁定工作。

  • 只有在一個Recyclerview嵌套在另一個Recyclerview中李皇,設(shè)定collectInitialPrefetchPositions才會生效削茁。

如果將此值設(shè)置為大于此視圖中可見的視圖數(shù)可能會導(dǎo)致不必要的綁定工作,并且會增加創(chuàng)建和活動使用的視圖數(shù)掉房。

3.多個RecycerView共用RecycledViewPool

在大多數(shù)APP中都有這樣一種場景茧跋,一個ViewPager中包含多個Fragment,而Fragment中主體是Recyclerview卓囚,并且Recyclerview中item view的布局是相同的瘾杭。例如 微博等


微博 截圖

這種情況下,Recyclerview可以設(shè)定統(tǒng)一的緩存池用來提高性能哪亿。

新建緩存池:

RecyclerView.RecycledViewPool viewPool=new RecyclerView.RecycledViewPool();

設(shè)定緩存池:

recyclerView.setRecycledViewPool(viewPool);

4.精確的更新數(shù)據(jù)使用DiffUtil

在Recyclerview中提供了多種數(shù)據(jù)數(shù)據(jù)刷新方式

  • notifyDataChanged()
    用于刷新全部數(shù)據(jù)粥烁,會導(dǎo)致整個布局重繪,所有的ViewHolder也會重新綁定蝇棉。
  • notifyItemXXX();
    用于刷新指定位置的Item數(shù)據(jù)讨阻。

雖然有了這些刷新方式,但是實際開發(fā)中篡殷,存在這樣一種情況变勇,新數(shù)據(jù)集與舊數(shù)據(jù)集僅有一部分數(shù)據(jù)存在差異。

例如:刷新一個聯(lián)系人列表,聯(lián)系人列表中部分聯(lián)系人的頭像有變化搀绣,但是姓名和手機號碼等信息未發(fā)生變化。這種情況以往都是使用notifyDataChanged方法刷新全部數(shù)據(jù)戳气,但是刷新全部數(shù)據(jù)的會導(dǎo)致整個布局重繪链患,Recyclerview中針對這種情況還提供了另一種粒度更小的刷新方式DiffUti

這里不打算去講DiffUtil的具體用法,只需要記住DiffUtil的使用場景即可:列表中存在多個Item的數(shù)據(jù)需要刷新瓶您,但是新數(shù)據(jù)集與舊數(shù)據(jù)集存在重復(fù)的情況

5.靈活設(shè)定setHasFixedSize
在Recyclerview中使用以下方法時麻捻,會觸發(fā)requestLayout()

  • onItemRangeChanged()
  • onItemRangeInserted()
  • onItemRangeRemoved()
  • onItemRangeMoved()

requestLayout()會重新計算item的大小,如果item的布局文件已經(jīng)將寬高設(shè)為固定大小呀袱,可以設(shè)定setHasFixedSize(true)贸毕,來避免Recyclerview重新計算item的大小。

6.優(yōu)化Item的布局
布局優(yōu)化是個老生長談的問題夜赵,本質(zhì)上就是減少嵌套明棍,ConstraintLayout是google推出的一個用于減少布局嵌套的新layout,但是在Recyclerview中使用ConstraintLayout會導(dǎo)致cpu使用率上升寇僧,暫時不推薦使用摊腋,不過ConstraintLayout 2.0版本已經(jīng)進入beta測試,期待后續(xù)會有優(yōu)化嘁傀。

7.數(shù)據(jù)非常少時兴蒸,使用ListView
不知道你有沒有考慮過這樣的問題,RecyclerView用已經(jīng)如此強大细办,用得人也越來越多橙凳,為什么最新的Android系統(tǒng)中ListView依然沒有被標注為"過時"。
RecyclerView重新設(shè)計了緩存機制笑撞,新的緩存機制更加強大岛啸,更適合處理大量數(shù)據(jù)的顯示,但是這種緩存機制會占據(jù)更多的內(nèi)存娃殖,當一個列表頁面實際數(shù)據(jù)項非常少的時候值戳,ListView往往比RecyclerView更合適。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炉爆,一起剝皮案震驚了整個濱河市堕虹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芬首,老刑警劉巖赴捞,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異郁稍,居然都是意外死亡赦政,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恢着,“玉大人桐愉,你說我怎么就攤上這事£桑” “怎么了从诲?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長靡羡。 經(jīng)常有香客問我系洛,道長,這世上最難降的妖魔是什么略步? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任描扯,我火速辦了婚禮,結(jié)果婚禮上趟薄,老公的妹妹穿的比我還像新娘绽诚。我一直安慰自己,他們只是感情好竟趾,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布憔购。 她就那樣靜靜地躺著,像睡著了一般岔帽。 火紅的嫁衣襯著肌膚如雪玫鸟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天犀勒,我揣著相機與錄音屎飘,去河邊找鬼。 笑死贾费,一個胖子當著我的面吹牛钦购,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播褂萧,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼押桃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了导犹?” 一聲冷哼從身側(cè)響起唱凯,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谎痢,沒想到半個月后磕昼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡节猿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年票从,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡峰鄙,死狀恐怖浸间,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吟榴,我是刑警寧澤发框,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站煤墙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宪拥。R本人自食惡果不足惜仿野,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望她君。 院中可真熱鬧脚作,春花似錦、人聲如沸缔刹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽校镐。三九已至亿扁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸟廓,已是汗流浹背从祝。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留引谜,地道東北人牍陌。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像员咽,于是被迫代替她去往敵國和親毒涧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容