阿里四面有三面都問了這個問題,在此做了整理,希望可以幫助到大家,歡迎查漏補缺。
資料處理和檢視載入分離
我們知道,從遠端拉取資料肯定是要放在非同步的,在我們拉取下來資料之後可能就匆匆把資料丟給了 VH 處理,其實,資料的處理邏輯我們也應該放在非同步處理,這樣 Adapter 在 notify change 後,ViewHolder 就可以簡單無壓力地做資料與檢視的繫結邏輯,比如:
mTextView.setText(Html.fromHtml(data).toString());
複製程式碼
這裡的 Html.fromHtml(data)
方法可能就是比較耗時的,存在多個 TextView
的話耗時會更為嚴重,這樣便會引發掉幀、卡頓,而如果把這一步與網路非同步執行緒放在一起,站在使用者角度,最多就是網路重新整理時間稍長一點。
資料優化
分頁拉取遠端資料,對拉取下來的遠端資料進行快取,提升二次載入速度;對於新增或者刪除資料通過 DiffUtil
來進行區域性重新整理資料,而不是一味地全域性重新整理資料。
佈局優化
減少過渡繪製
減少佈局層級,可以考慮使用自定義 View 來減少層級,或者更合理地設定佈局來減少層級,不推薦在 RecyclerView 中使用 ConstraintLayout
,有很多開發者已經反映了使用它效果更差,相關連結有:Is ConstraintLayout that slow?、constraintlayout 1.1.1 not work well in listview。
減少 xml 檔案 inflate 時間
這裡的 xml 檔案不僅包括 layout 的 xml,還包括 drawable 的 xml,xml 檔案 inflate 出 ItemView 是通過耗時的 IO 操作,尤其當 Item 的複用機率很低的情況下,隨著 Type 的增多,這種 inflate 帶來的損耗是相當大的,此時我們可以用程式碼去生成佈局,即 new View()
的方式,只要搞清楚 xml 中每個節點的屬性對應的 API 即可。
減少 View 物件的建立
一個稍微複雜的 Item 會包含大量的 View,而大量的 View 的建立也會消耗大量時間,所以要儘可能簡化 ItemView;設計 ItemType 時,對多 ViewType 能夠共用的部分儘量設計成自定義 View,減少 View 的構造和巢狀。
其他
其他並不代表不重要,而是我不能把他們進行分類哈,其中可能某些操作會對你的 RecyclerView 有很大的優化。
-
升級
RecycleView
版本到 25.1.0 及以上使用 Prefetch 功能,可參考 RecyclerView 資料預取。 -
如果 Item 高度是固定的話,可以使用
RecyclerView.setHasFixedSize(true);
來避免requestLayout
浪費資源; -
設定
RecyclerView.addOnScrollListener(listener);
來對滑動過程中停止載入的操作。 -
如果不要求動畫,可以通過
((SimpleItemAnimator) rv.getItemAnimator()).setSupportsChangeAnimations(false);
把預設動畫關閉來提升效率。 -
對
TextView
使用String.toUpperCase
來替代android:textAllCaps="true"
。 -
對
TextView
使用StaticLayout
或者DynamicLayout
的自定義View
來代替它。 -
通過重寫
RecyclerView.onViewRecycled(holder)
來回收資源。 -
通過
RecycleView.setItemViewCacheSize(size);
來加大RecyclerView
的快取,用空間換時間來提高滾動的流暢性。 -
如果多個
RecycledView
的Adapter
是一樣的,比如巢狀的RecyclerView
中存在一樣的Adapter
,可以通過設定RecyclerView.setRecycledViewPool(pool);
來共用一個RecycledViewPool
。 -
對
ItemView
設定監聽器,不要對每個 Item 都呼叫addXxListener
,應該大家公用一個XxListener
,根據ID
來進行不同的操作,優化了物件的頻繁建立帶來的資源消耗。 -
通過 getExtraLayoutSpace 來增加 RecyclerView 預留的額外空間(顯示範圍之外,應該額外快取的空間),如下所示:
new LinearLayoutManager(this) { @Override protected int getExtraLayoutSpace(RecyclerView.State state) { return size; } }; 複製程式碼
結語
我正在打造一個幫助 Android 開發者們拿到更好 offer 的面試庫————安卓 offer 收割基,歡迎 star,覺得不錯的可以持續關注,有興趣的可以一起加入進來和我一同打造。