You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DataBinding+RecyclerView中实现列表项点击跳转详情页?

实现RecyclerView列表项点击跳转的优雅方案

问题背景

前端转Kotlin开发Android应用,已基于DataBinding、Koin、Room搭建了展示法国省份列表的项目,用DataBinding实现了RecyclerView的自定义Adapter,但不知道如何优雅实现列表项点击跳转详情页的逻辑:

  • 尝试过给Adapter关联ViewModel,但ViewModel没有Context无法启动Activity
  • 希望在Adapter中传入点击函数,但不知道如何在XML中绑定该函数

解决方案

我们可以通过给Adapter传递点击回调lambda,结合DataBinding在XML中直接绑定点击事件的方式实现,具体步骤如下:

1. 修改Adapter,添加点击回调参数

更新DepartmentListAdaptater,添加接收点击事件的lambda参数,并在绑定数据时将回调传递给XML:

class DepartmentListAdaptater(
    private val onDepartmentClick: (Department) -> Unit
) : RecyclerView.Adapter<DepartmentListAdaptater.ViewHolder>() {
    private var dataSet: List<Department>? = null

    inner class ViewHolder(private val binding: DepartmentListRowBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(department: Department) {
            binding.department = department
            // 将点击回调传递给Binding
            binding.onDepartmentClick = onDepartmentClick
        }
    }

    fun submitList(list: List<Department>) {
        dataSet = list
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = DepartmentListRowBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun getItemCount(): Int = dataSet?.size ?: 0

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        dataSet?.get(position)?.let { holder.bind(it) }
    }
}

2. 修改XML布局,绑定点击事件

在department_list_row.xml的<data>块中添加点击回调变量,并给可点击的LinearLayout绑定点击事件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="department" type="com.navalex.francemap.data.entity.Department" />
        <!-- 添加点击回调变量,类型为接收Department参数的函数 -->
        <variable 
            name="onDepartmentClick" 
            type="kotlin.jvm.functions.Function1<com.navalex.francemap.data.entity.Department, kotlin.Unit>" />
    </data>

    <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="72dp">
        <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:background="@drawable/list_item_bg"
                android:layout_alignParentEnd="true"
                android:layout_alignParentTop="true"
                android:layout_alignParentBottom="true"
                android:clickable="true"
                <!-- 绑定点击事件,触发回调并传入当前department -->
                android:onClick="@{() -> onDepartmentClick.invoke(department)}"
                tools:ignore="UselessParent">

            <TextView
                    android:id="@+id/textView"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:paddingRight="16dp"
                    android:text="@{department.nom}"
                    android:paddingLeft="16dp"/>

        </LinearLayout>
    </RelativeLayout>
</layout>

3. 在MainActivity中实现跳转逻辑

创建Adapter时传入点击回调lambda,在其中启动详情页(假设详情页为DepartmentDetailActivity,需传递省份数据):

class MainActivity : AppCompatActivity() {

    private val mViewModel: DepartmentsViewModel by viewModel()
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.toolbar.title = "Liste des départements"

        // 创建Adapter时传入点击回调
        val adapter = DepartmentListAdaptater { department ->
            // 启动详情页,传递省份数据
            val intent = Intent(this, DepartmentDetailActivity::class.java)
            // 需确保Department实现Parcelable/Serializable接口
            intent.putExtra("DEPARTMENT_DATA", department)
            startActivity(intent)
        }
        binding.recyclerview.adapter = adapter
        binding.recyclerview.layoutManager = LinearLayoutManager(this)
        mViewModel.allDepartments.observe(this, Observer { data -> adapter.submitList(data) })
    }
}

补充说明

  • 需确保Department类实现Parcelable或Serializable接口,才能通过Intent传递对象
  • 该方案将跳转逻辑与Adapter解耦,Adapter仅负责展示数据和传递点击事件,跳转逻辑由Activity处理,符合单一职责原则
  • 避免在Adapter中持有Context,降低内存泄漏风险

内容的提问来源于stack exchange,提问作者Navalex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 02:50:27