掌握 Android 中的 RecyclerView 優化
- 一、RecyclerView Pool以及何時使用它
- 二、onCreateViewHolder 和 onBindViewHolder
- 三、優化 RecyclerView 的不同方法
- 四、視圖無效與請求布局
- 五、ViewHolder模式
- 六、默認的廢料和臟視圖類型
- 七、結論
RecyclerView 是 Android 中一個功能強大的小部件,用于高效顯示大型列表或數據網格。為了確保應用程序的性能和響應能力,優化 RecyclerView 實現至關重要。這里我們將探討各種技術和概念,幫助充分利用 RecyclerView。
一、RecyclerView Pool以及何時使用它
RecyclerView Pool 是一種幫助管理 RecyclerView 中視圖的內存和性能的機制。它本質上是一個緩存,用于保存當前在屏幕上不可見但在不久的將來可能再次需要的視圖。這顯著減少了每次新項目進入可見區域時膨脹新視圖的開銷。
何時使用 RecyclerView Pool:
- 處理大型列表或數據網格時使用它。
- 當列表中的項目具有不同的視圖類型時,請選擇 RecyclerView Pool。
二、onCreateViewHolder 和 onBindViewHolder
在RecyclerView中,onCreateViewHolder和onBindViewHolder是適配器中必不可少的方法。它們共同為列表中的每個項目創建和綁定視圖。
- onCreateViewHolder在需要創建新視圖時被調用。它負責擴展布局并創建 ViewHolder 實例。
- 當現有視圖被新項目重用時,將調用onBindViewHolder 。它將數據綁定到視圖持有者,允許您更新視圖的內容。
- onBindViewHolder不應該用于綁定點擊偵聽器,我們應該注意我們在其中執行的匿名對象或任務。仔細閱讀下面的代碼,然后我會解釋為什么?
class MyAdapter ( private val items: List<Item>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { inside class ViewHolder (itemView: View) : RecyclerView.ViewHolder(itemView) { init { itemView.setOnClickListener { // 處理項目click here val position = adapterPosition if (position != RecyclerView.NO_POSITION) { val clickedItem = items[position] // 處理 clickedItem 的點擊事件} } } } override fun onCreateViewHolder (parent: ViewGroup , viewType: Int ) : ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, Parent, false ) return ViewHolder(view) } override fun onBindViewHolder (holder: ViewHolder ,position: Int ) { val currentItem = items[position] / / 此處將數據綁定到視圖持有者} override fun getItemCount () = items.size
}
- 在onBindViewHolder中,為每個項目單獨生成單擊偵聽器,從而導致多個偵聽器實例。通過將點擊監聽器放置在 中ViewHolder,它們在 ViewHolder 創建時就形成了,由于 ViewHolder 的可重用性,提高了內存效率。
三、優化 RecyclerView 的不同方法
- 使用圖像庫:
處理圖像時,建議使用提供位圖池的圖像庫。這可以防止過多的內存使用和頻繁的垃圾收集。
Glide.with( this ) .load(imageUrl) .placeholder(R.drawable.placeholder_image) .error(R.drawable.error_icon) .into(imageView)
- 優化圖像尺寸:從服務器獲取圖像尺寸和寬高比,以避免不必要的調整大小和縮放。
- setHasStableIds:此方法應用于setHasStableIds(true)啟用穩定的項目 ID。這有助于有效地更新和重新排序項目,而無需不必要的重新綁定。
class MyAdapter ( private val itemList: List<Item>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { init { setHasStableIds( true ) // 為此適配器啟用穩定 ID} //....}
- setHasFixedSize:如果RecyclerView大小本身是固定的并且不會因其內容而改變,則使用它setHasFixedSize(true)可以通過避免不必要的布局計算來幫助提高性能。
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.setHasFixedSize( true ) // 為 RecyclerView 啟用固定大小
- setItemViewCacheSize:使用此方法調整緩存大小,以控制保留多少個離屏視圖。這可以幫助管理內存使用。
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.setItemViewCacheSize( 10 ) // 根據項目大小將視圖緩存大小設置為自定義值
四、視圖無效與請求布局
- Invalidate:用于指示視圖的內容已更改并且需要重新繪制。
- requestLayout:用于請求新的布局通道,影響視圖的大小和位置。
您可能想知道為什么我突然談論invalidate與requestLayout。讓我解釋。
我討論了“無效”與“請求布局”,以說明它們如何影響視圖的生命周期。這會影響屏幕重繪時間,過多的布局和繪制階段會降低性能。要優化 Android 頁面,尤其是 RecyclerView,徹底掌握視圖生命周期至關重要。
讓我用一個例子來進一步解釋一下:
當 TextView 的 wrap_content 與 100dp 固定時,將或應該調用什么(invalidate 或 requestLayout)?
回答:
當 TextView 的寬度設置為 時wrap_content,調用requestLayout()會更合適。這是因為這requestLayout()表明視圖層次結構需要重新測量和布局,以確保內容正確地適合邊界。
當 TextView 的寬度固定時(例如,設置為特定值,如100dp),調用invalidate()通常就足夠了。它通知系統視圖的內容已更改,并且需要在現有布局范圍內重新繪制。這可以避免在更新視圖外觀時進行不必要的重新布局計算。
五、ViewHolder模式
ViewHolder 模式是一種設計模式,它通過最大限度地減少對 .recyclerview 的調用次數來增強 recyclerview 的性能findViewById()。它涉及創建一個 ViewHolder 類,該類保存對項目布局中視圖的引用。這允許在用戶滾動列表時有效地重用視圖。有關 ViewHolder 模式的綜合示例,請查看此鏈接。
六、默認的廢料和臟視圖類型
在RecyclerView中,每種視圖類型的廢視圖和臟視圖的默認計數設置為 5。對于標題等僅 1 或 2 個剪貼視圖就足夠的情況,此通用編號可能不是最佳選擇。廢料視圖是可重用的、分離的視圖,可以輕松地重新附加。
為了提高內存效率,您可以根據每個特定視圖類型的流行程度自定義池大小,從而定制剪貼視圖行為。這種方法通過有效管理RecyclerView中不同類型項目的剪貼視圖數量,確保優化內存使用。
val customRecycledViewPool = RecyclerView.RecycledViewPool().apply { setMaxRecycledViews(viewType, poolSize) // 設置自定義 viewType 和 poolSize}
七、結論
優化 RecyclerView 實施對于保持流暢且響應迅速的用戶體驗至關重要。通過理解 RecyclerView Pool 和 ViewHolder 模式等概念,并優化視圖創建和綁定,您可以確保您的應用程序有效地處理大量數據。
請記住,每種優化技術都有特定的目的,并且應用這些技術的組合可以顯著提高 RecyclerView 的性能。