🚀 RecyclerView 进阶优化指南 相比之前的版本,这次的改进包括:
✅ 使用 DiffUtil
优化数据更新 (避免 notifyDataSetChanged()
)
✅ 使用 ViewBinding
简化 ViewHolder
代码
✅ 封装 Adapter
支持 MutableList
(支持增删改查)
✅ 优化 onClick
事件,让 RecyclerView
更易扩展
✅ 支持 Grid/瀑布流/线性布局
1️⃣ 添加 RecyclerView 依赖 确保你的 build.gradle
添加了:
1 2 3 4 dependencies { implementation 'androidx.recyclerview:recyclerview:1.3.2' implementation 'androidx.viewbinding:viewbinding:7.3.1' // 使用 ViewBinding }
2️⃣ 在 activity_main.xml
中添加 RecyclerView
1 2 3 4 5 <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"/>
3️⃣ 创建数据模型 1 2 3 4 5 6 data class Diary( val id: Int, // 方便更新和删除 val title: String, val content: String, val date: String )
4️⃣ 使用 DiffUtil
优化 Adapter
🚀 DiffUtil
可以高效更新 RecyclerView
,避免全量刷新,提高性能。
创建 DiaryDiffCallback
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class DiaryDiffCallback( private val oldList: List<Diary>, private val newList: List<Diary> ) : DiffUtil.Callback() { override fun getOldListSize(): Int = oldList.size override fun getNewListSize(): Int = newList.size // 判断是否是同一项(通常比较 ID) override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition].id == newList[newItemPosition].id } // 判断内容是否相同(避免不必要的刷新) override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition] == newList[newItemPosition] } }
5️⃣ 优化 Adapter
(使用 ViewBinding
) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class DiaryAdapter( private var diaryList: MutableList<Diary>, // 让数据可变 private val onItemClick: (Diary) -> Unit ) : RecyclerView.Adapter<DiaryAdapter.DiaryViewHolder>() { // 使用 ViewBinding 简化 ViewHolder class DiaryViewHolder(val binding: ItemDiaryBinding) : RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DiaryViewHolder { val binding = ItemDiaryBinding.inflate(LayoutInflater.from(parent.context), parent, false) return DiaryViewHolder(binding) } override fun onBindViewHolder(holder: DiaryViewHolder, position: Int) { val diary = diaryList[position] with(holder.binding) { tvTitle.text = diary.title tvContent.text = diary.content tvDate.text = diary.date root.setOnClickListener { onItemClick(diary) } // 处理点击事件 } } override fun getItemCount(): Int = diaryList.size // 🚀 使用 DiffUtil 刷新数据,避免全量刷新 fun updateData(newList: List<Diary>) { val diffResult = DiffUtil.calculateDiff(DiaryDiffCallback(diaryList, newList)) diaryList.clear() diaryList.addAll(newList) diffResult.dispatchUpdatesTo(this) } // 增删改查方法 fun addDiary(diary: Diary) { diaryList.add(0, diary) // 插入到第一个位置 notifyItemInserted(0) } fun removeDiary(position: Int) { if (position in diaryList.indices) { diaryList.removeAt(position) notifyItemRemoved(position) } } }
6️⃣ 创建 item_diary.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp" android:background="@android:color/white"> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="@android:color/black" android:textStyle="bold"/> <TextView android:id="@+id/tvContent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="@android:color/darker_gray" android:maxLines="2" android:ellipsize="end"/> <TextView android:id="@+id/tvDate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" android:textColor="@android:color/holo_blue_dark"/> </LinearLayout>
7️⃣ 在 MainActivity
绑定 RecyclerView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class MainActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView private lateinit var diaryAdapter: DiaryAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView = findViewById(R.id.recyclerView) recyclerView.layoutManager = LinearLayoutManager(this) // 初始数据 val diaryList = mutableListOf( Diary(1, "今日心情", "今天天气很好,心情愉快!", "2025-03-17"), Diary(2, "学习 Kotlin", "RecyclerView 真的很好用!", "2025-03-16") ) // 绑定 Adapter diaryAdapter = DiaryAdapter(diaryList) { diary -> Toast.makeText(this, "点击了: ${diary.title}", Toast.LENGTH_SHORT).show() } recyclerView.adapter = diaryAdapter // 模拟 3 秒后刷新数据 Handler(Looper.getMainLooper()).postDelayed({ val newData = diaryList + Diary(3, "记账", "今天吃了火锅,花了 120 元", "2025-03-15") diaryAdapter.updateData(newData) }, 3000) } }
8️⃣ 可选优化 (1)网格布局 1 recyclerView.layoutManager = GridLayoutManager(this, 2) // 2 列
(2)瀑布流布局 1 recyclerView.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
🎯 总结
改进点
说明
✅ 使用 DiffUtil
优化数据更新 ,避免 notifyDataSetChanged()
✅ 使用 ViewBinding
减少 findViewById
代码 ,提高可读性
✅ 封装增删改查方法
addDiary()
和 removeDiary()
✅ 支持 MutableList
让数据可变 ,更方便操作
✅ 支持 Grid/瀑布流布局
适配不同 UI 需求
🚀 这样写的 RecyclerView
更高效、更易扩展!你可以直接用在 Kotlin 日记本 App 里。 🎉