RecyclerView使用封裝與優化

舒大飛發表於2018-03-30

   最近優化了專案裡的列表展示,順便對RecyclerView的使用做了重新的封裝,目的是當列表的需求比較複雜的時候,依然能夠保持邏輯的清晰和解耦,同時通過封裝來使複雜列表的效能得到一定的保證。

當然如果是非常簡單的列表的話,其實Android原生的RecyclerView加上Adapter就已經比較便捷了,沒有必要去做過度的封裝了。

專案GitHub地址: github.com/zhengcx/Ins…

   每一個對專案的重構或者重新封裝都是出於對現狀的不滿,那麼我們就從這個封裝專案解決了哪些問題來展開這篇博文吧。

1.解決重複的全域性重新整理

   需要注意一下你的專案裡對列表的使用,特別是載入更多時是否都是重複的全域性重新整理,這對複雜列表的效能影響較大,你需要考慮每次重新整理不去重新整理那些不需要重新整理的item,一個是對效能會有提高,另一個頁面上使用者的體驗也會好很多,本專案提供了全域性重新整理和增量重新整理的相關方法,保證載入更多或者操作單個item時只區域性重新整理。

2.解決header/Footer的增刪效率

   RecyclerView本身並沒有提供像ListView那樣便捷的新增header/footer的方法,所以需要我們自己去實現。

網上主要有兩種:一種是採用wrap的方式使header、footer和普通item區別開,而另一種方式使把header、footer也當做是一種itemType來做。

   這裡我們採用了第二種方式,提供了便捷新增header/footer的方法,當然把header\footer當做一種itemType來看待,則當header/footer發生增刪(特別是header)時,則會使列表發生全域性的重新整理,這裡優化的點是對RecyclerView來說他的header永遠只有一個,是一個ViewGroup,之後要新增或者刪除一個或多個header,都只是往這個ViewGroup裡增刪View,將不會對整個列表產生重新整理,提供效能和體驗。

3. 解決列表多itemType時程式碼不夠清晰的問題

   當你的列表會存在多種複雜的itemType時,很容易時Adapter裡的程式碼產生混亂,且不夠清晰,很難擴充。我們封裝的目的是:

1.讓每種itemType的處理邏輯交給各自的itemDelegate去處理,實現不同itemType處理邏輯的解耦

2.讓程式碼易於擴充,也就是說不管今後要再新增多少種itemType,都能做到非常清晰,非常便捷。

專案裡通過DelegateScheduler來管理排程不同itemType的處理邏輯,使多itemType變得清晰易擴充。

4.解決狀態View導致過度繪製的問題

   我們的列表通常都需要好幾種顯示載入狀態的View,比如loadingView、載入失敗View、載入資料為空View。如果你的做法是在佈局檔案裡先寫好這幾種View然後通過設定是否可見來控制,顯然這會引起佈局巢狀過渡繪製的問題,當然你可以利用ViewStub來做一些優化,但是治標不治本,當這些狀態View被inflate一次後,依然會存在這種問題。

   如果你把這些狀態View也當做是一種itemType呢,讓它與普通item一樣參與回收,參與cache,是不是就可以解決這個問題,這是我目前看到想到的比較理想的方式,當然可能有更好的方式。

5.解決上拉載入更多問題

   顯然如果你把上拉載入更多這個功能放在你的業務程式碼裡去監聽是不合適的,我們需要封裝一下,讓recyclerView自動就帶有這個功能,直接使用就可以了。

   本專案給上拉載入更多提供了兩種不同的監聽方式,看個人喜好自己選擇。

1.實時監聽,也就是說只要使用者滑動,那麼就會實時監聽判斷要不要開始載入下一頁資料,這一種的好處是讓列表預載入更加實時,基本可以實時使用者可以不斷的下拉,使使用者感知不到我們的載入過程。

2.另一種是隻有當列表滾動狀態發生改變時才會發起是否載入下一頁資料的判斷,這一種基本是使用者從滑動到停止時才會發起下一頁的載入。

當然兩種方式提前多少個item發起預載入下一頁都是可以由你自己來設定這個引數,目前預設是採用第二種方式,可以通過設定來使用第一種方式。

6. 解決item的點選事件重複繫結的問題

   RecyclerView沒有像ListView那樣提供setOnItemCLickListener()方法來繫結item的點選事件,所以我們一般都會自己去設定這個item的點選事件,這樣子很容易就把點選事件多次重複設定了。

   這裡封裝提供了setOnItemClickListener()方法,讓你可以放心的設定item點選事件,並且在回撥裡提供該item所繫結的資料,以及item的position,該item的型別等重要資訊,可以使你在多種itemType的列表裡的點選事件里正確的做各種你想做的事情。

對列表效能問題的建議

   其實對於一些複雜的列表,效能問題顯得尤為重要,上面說了一個是儘量去做區域性重新整理而不是全量重新整理,一個是儘量減少過度繪製。還有一個非常重要的是每個版本都要去關注你的bindViewHolder()裡的邏輯是否有耗時嚴重的方法或操作,列表效能出現問題,很大概率就是你的bindViewHolder()中有叫耗時操作,排查也很好排查,通過SysTrace+TraceView可以很快找到耗時的方法和效能的瓶頸,然後做針對性的優化就可以了。

專案GitHub地址: github.com/zhengcx/Ins…

最後,希望世界上的每一個列表都絲絲如滑~~~

相關文章