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

基于Dagger在Epoxy Controller中实现RecyclerView条目点击跳转的最佳方式

解决Airbnb Epoxy RecyclerView条目点击跳转Activity的Context问题

你的思路完全没问题,通过在EpoxyController中定义回调接口、让主Activity实现接口的方式,确实是Epoxy里处理条目交互的标准做法。我来把具体的代码细节补全,帮你搞定Context的问题:

步骤1:在EpoxyController中定义点击回调接口

首先在你的EpoxyController内部(或者单独定义,放在控制器里更内聚)创建一个接口,用来传递点击事件,方法参数带上View,这样就能通过View获取Context:

class YourEpoxyController : EpoxyController() {
    // 定义点击回调接口
    interface OnItemClickListener {
        fun onItemClicked(item: YourDataModel, view: View)
    }

    // 持有回调实例
    var itemClickListener: OnItemClickListener? = null

    override fun buildModels() {
        // 构建EpoxyModel时,把回调传递给每个model
        yourDataList.forEach { item ->
            YourItemModel_()
                .id(item.id)
                .data(item)
                .clickListener { view ->
                    itemClickListener?.onItemClicked(item, view)
                }
                .addTo(this)
        }
    }
}

步骤2:编写你的EpoxyModel

在对应的ItemModel中,添加clickListener的字段,用来接收点击回调(如果用注解生成Model,直接定义对应字段即可):

// 注解生成的EpoxyModel示例
@EpoxyModelClass(layout = R.layout.your_item_layout)
abstract class YourItemModel : EpoxyModelWithHolder<YourItemModel.Holder>() {

    @EpoxyAttribute
    lateinit var data: YourDataModel

    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
    var clickListener: ((View) -> Unit)? = null

    override fun bind(holder: Holder) {
        super.bind(holder)
        // 给条目根布局设置点击监听
        holder.itemView.setOnClickListener {
            clickListener?.invoke(it)
        }
        // 绑定其他数据到View
        holder.titleTv.text = data.title
    }

    class Holder : EpoxyHolder() {
        lateinit var titleTv: TextView
        override fun bindView(itemView: View) {
            titleTv = itemView.findViewById(R.id.title_tv)
        }
    }
}

步骤3:在主Activity中实现接口并初始化控制器

让主Activity实现刚才定义的OnItemClickListener接口,在回调方法里通过View的Context启动目标Activity:

class MainActivity : AppCompatActivity(), YourEpoxyController.OnItemClickListener {

    private lateinit var epoxyController: YourEpoxyController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化控制器并设置回调
        epoxyController = YourEpoxyController().apply {
            itemClickListener = this@MainActivity
        }

        // 绑定控制器到RecyclerView
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.setController(epoxyController)

        // 加载数据并刷新
        loadData()
    }

    private fun loadData() {
        // 模拟数据加载
        val dataList = listOf(YourDataModel(1, "测试条目1"), YourDataModel(2, "测试条目2"))
        epoxyController.setData(dataList) // 假设控制器有setData方法更新数据
    }

    override fun onItemClicked(item: YourDataModel, view: View) {
        // 通过view.getContext()获取Context启动Activity
        val intent = Intent(view.context, TargetActivity::class.java)
        intent.putExtra("ITEM_ID", item.id)
        view.context.startActivity(intent)
        // 也可以直接用Activity本身(Activity是Context子类)
        // startActivity(Intent(this, TargetActivity::class.java).putExtra("ITEM_ID", item.id))
    }
}

额外注意点

  • 若担心内存泄漏,可以用WeakReference持有回调实例,只要控制器生命周期和Activity一致(比如在Activity销毁时把itemClickListener置为null),一般不会有问题。
  • 如果用Java开发,核心逻辑完全一致,只需要调整语法细节即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:09:51