一、RecyclerView 核心概念
1. 基本組件關系
2. 核心組件作用
Adapter:數據與視圖的橋梁
LayoutManager:控制布局方式(線性/網格/瀑布流)
ViewHolder:緩存視圖組件
ItemDecoration:添加分割線等裝飾
ItemAnimator:處理增刪動畫
二、基礎使用流程
1. 添加依賴
implementation 'androidx.recyclerview:recyclerview:1.3.2'
2. XML布局
<androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"/>
3. 實現 Adapter
class MyAdapter(private val data: List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {// 創建 ViewHolderoverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)return MyViewHolder(view)}// 綁定數據override fun onBindViewHolder(holder: MyViewHolder, position: Int) {holder.bind(data[position])}override fun getItemCount() = data.size// ViewHolder 定義inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {private val textView: TextView = itemView.findViewById(R.id.tv_item)fun bind(item: String) {textView.text = item}}
}
4. 設置 RecyclerView
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = MyAdapter(listOf("Item 1", "Item 2", "Item 3"))
三、ViewHolder 生命周期詳解
關鍵生命周期方法:
onCreateViewHolder()
:創建新視圖onBindViewHolder()
:綁定數據onViewAttachedToWindow()
:視圖進入屏幕onViewDetachedFromWindow()
:視圖離開屏幕onViewRecycled()
:視圖進入回收池(可在此釋放資源)
四、性能優化策略
1. 基礎優化
// 設置固定尺寸提升測量效率
recyclerView.setHasFixedSize(true) // 增加緩存數量(默認=2)
recyclerView.itemViewCacheSize = 10
2. 高效數據綁定
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {// 使用 payload 實現局部更新holder.bind(data[position])
}// 使用 DiffUtil 智能更新
val diffResult = DiffUtil.calculateDiff(MyDiffCallback(oldList, newList))
diffResult.dispatchUpdatesTo(adapter)
3. 視圖復用優化
// Adapter 中重寫 getItemViewType()
override fun getItemViewType(position: Int): Int {return when (data[position].type) {ItemType.TEXT -> 0ItemType.IMAGE -> 1}
}// 根據 viewType 創建不同 ViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) {return when (viewType) {0 -> TextViewHolder(...)1 -> ImageViewHolder(...)}
}
4. 圖片加載優化
fun bind(item: Item) {Glide.with(itemView).load(item.imageUrl).apply(RequestOptions().override(100, 100)) // 限制尺寸.into(imageView)
}override fun onViewRecycled() {Glide.with(itemView).clear(imageView) // 及時釋放
}
五、事件監聽實現
1. 點擊事件處理
// 在 ViewHolder 中設置監聽
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {init {itemView.setOnClickListener {val pos = adapterPositionif (pos != RecyclerView.NO_POSITION) {// 通過接口回調事件listener?.onItemClick(pos)}}}
}// 定義回調接口
interface OnItemClickListener {fun onItemClick(position: Int)
}
2. 長按事件
itemView.setOnLongClickListener {val pos = adapterPositionif (pos != RecyclerView.NO_POSITION) {listener?.onItemLongClick(pos)true} else false
}
3. 滑動監聽
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {// dy > 0:向上滾動// dy < 0:向下滾動}override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {when (newState) {RecyclerView.SCROLL_STATE_IDLE -> { /* 停止滾動 */ }RecyclerView.SCROLL_STATE_DRAGGING -> { /* 用戶拖動 */ }RecyclerView.SCROLL_STATE_SETTLING -> { /* 慣性滑動 */ }}}
})
六、高級技巧
1. 嵌套滾動優化
<!-- 子RecyclerView設置 -->
android:nestedScrollingEnabled="false"
2. 預加載實現
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {val lastVisible = (layoutManager as LinearLayoutManager).findLastVisibleItemPosition()if (lastVisible > itemCount - 5) {// 觸發預加載}}
})
3. 高效更新策略
// 使用 ListAdapter 自動處理差異更新
class MyAdapter : ListAdapter<Item, MyViewHolder>(DiffCallback()) {// 自動計算差異更新
}class DiffCallback : DiffUtil.ItemCallback<Item>() {override fun areItemsTheSame(old: Item, new: Item) = old.id == new.idoverride fun areContentsTheSame(old: Item, new: Item) = old == new
}
最佳實踐總結
ViewHolder模式:必須使用避免重復findViewById
局部更新:優先使用DiffUtil/ListAdapter
資源釋放:在onViewRecycled()中釋放圖片等資源
事件委托:通過接口回調代替在Adapter中處理邏輯
類型區分:多類型視圖使用getItemViewType()
內存監控:使用Profiler檢測滾動時的內存波動