0Pricing
Android Academy · 课时

RecyclerView 点击事件

处理 RecyclerView 中的项目点击和长按,将点击监听器传递给适配器,并在点击项目时导航到详情页面。

RecyclerView 点击事件 是 CoddyKit 上的免费 Android Academy 课时。 这是第 3 节课,共 6 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 6 节课。

让列表项可点击

RecyclerView 没有像 ListView 那样内置的点击监听器。您需要在 Adapter 中添加点击监听器。

推荐的模式是:将 lambda(回调)传递给 Adapter 的构造函数。当用户点击某个列表项时,Adapter 会将选中的列表项传给 lambda,由 Activity 处理后续操作。

带点击回调的 Adapter

为 Adapter 添加一个 onItemClick lambda 参数:

class FruitAdapter(
    private val fruits: List<Fruit>,
    private val onItemClick: (Fruit) -> Unit
) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val tvName: TextView = view.findViewById(R.id.tvName)
        val tvCalories: TextView = view.findViewById(R.id.tvCalories)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_fruit, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val fruit = fruits[position]
        holder.tvName.text = fruit.name
        holder.tvCalories.text = "${fruit.calories} kcal"
        // Set click listener on the whole item
        holder.itemView.setOnClickListener {
            onItemClick(fruit)
        }
    }

    override fun getItemCount() = fruits.size
}

在 Activity 中处理点击

在 Activity 中传入一个用于跳转到详情页面的 lambda:

val adapter = FruitAdapter(fruits) { fruit ->
    // Called when user taps a fruit
    val intent = Intent(this, FruitDetailActivity::class.java)
    intent.putExtra("FRUIT_NAME", fruit.name)
    intent.putExtra("FRUIT_CALORIES", fruit.calories)
    startActivity(intent)
}

binding.recyclerView.apply {
    this.adapter = adapter
    layoutManager = LinearLayoutManager(this@MainActivity)
}

在详情页面接收数据

在详情 Activity 中读取附加数据:

class FruitDetailActivity : AppCompatActivity() {

    private lateinit var binding: ActivityFruitDetailBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityFruitDetailBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val name = intent.getStringExtra("FRUIT_NAME") ?: "Unknown"
        val calories = intent.getIntExtra("FRUIT_CALORIES", 0)

        binding.tvDetailName.text = name
        binding.tvDetailCalories.text = "$calories kcal"
    }
}

使用 DiffUtil 高效更新

列表数据发生变化时,不要调用 notifyDataSetChanged()——它会重绘所有内容。请改用 DiffUtil:

  • 计算新旧列表之间的最小差异
  • 只为发生变化的列表项播放动画
  • 带来更好的性能和用户体验

现代的做法是使用 ListAdapter,它会自动使用 DiffUtil。

使用 DiffUtil 的 ListAdapter

扩展 ListAdapter,即可自动为列表更新添加动画:

class FruitAdapter(
    private val onItemClick: (Fruit) -> Unit
) : ListAdapter<Fruit, FruitAdapter.ViewHolder>(DIFF_CALLBACK) {

    companion object {
        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Fruit>() {
            override fun areItemsTheSame(old: Fruit, new: Fruit) =
                old.name == new.name
            override fun areContentsTheSame(old: Fruit, new: Fruit) =
                old == new  // data class equals()
        }
    }

    // ... ViewHolder and onCreateViewHolder same as before ...

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val fruit = getItem(position)  // use getItem(), not fruits[position]
        holder.tvName.text = fruit.name
        holder.itemView.setOnClickListener { onItemClick(fruit) }
    }
}

提交新列表

使用 ListAdapter 时,调用 submitList() 更新列表。DiffUtil 会自动处理动画:

// In Activity:
val adapter = FruitAdapter { fruit ->
    // handle click
}
binding.recyclerView.adapter = adapter

// Initial data
adapter.submitList(fruits)

// Later, update with new data (e.g. after filtering):
val filtered = fruits.filter { it.calories < 100 }
adapter.submitList(filtered)  // DiffUtil animates the change

长按与上下文菜单

您还可以在 onBindViewHolder 中设置 setOnLongClickListener,以响应长按:

  • 让监听器返回 true,以消费此事件
  • 使用它显示删除或编辑对话框
  • 或者使用 ItemTouchHelper 实现滑动删除

添加列表项装饰

使用 DividerItemDecoration 在列表项之间添加视觉分隔:

binding.recyclerView.apply {
    adapter = fruitAdapter
    layoutManager = LinearLayoutManager(this@MainActivity)
    addItemDecoration(
        DividerItemDecoration(
            this@MainActivity,
            DividerItemDecoration.VERTICAL
        )
    )
}

快速检查

在 RecyclerView Adapter 中处理列表项点击的推荐方式是什么?

回顾:RecyclerView 点击事件

现在,您可以构建交互式列表:

  • 将 lambda 回调传递给 Adapter 构造函数
  • 在 onBindViewHolder 中调用 holder.itemView.setOnClickListener
  • 通过 Intent 传递附加数据,跳转到详情页面
  • 使用 ListAdapter + DiffUtil 实现流畅的动画更新
  • 调用 submitList() 更新显示的数据

下一步:使用 SharedPreferences 在本地持久化数据。

常见问题解答

「RecyclerView 点击事件」课时是免费的吗?

是的 — 「RecyclerView 点击事件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 6 节课。

「RecyclerView 点击事件」这节课中我会学到什么?

处理 RecyclerView 中的项目点击和长按,将点击监听器传递给适配器,并在点击项目时导航到详情页面。 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Android Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 6 节。

「RecyclerView 点击事件」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Android Academy 课中编写并运行代码吗?

能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Kotlin 集合
  2. RecyclerView 基础
  3. RecyclerView 点击事件
  4. SharedPreferences
  5. DataStore 偏好设置
  6. 适配器与 DiffUtil
← 返回 Android Academy