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

Android Kotlin中如何从Adapter启动Activity?遇Context获取问题

嘿,我来帮你搞定这个问题!你在ViewHolder的onClick里拿不到Context,本质是因为MyViewHolder作为Kotlin的嵌套类(默认是静态的),没法直接访问外部Adapter里的activity变量。下面给你几个实用的解决方案,从简单到推荐的解耦方式都有:

解决方案1:直接从itemView获取Context(最简洁)

其实ViewHolder持有的itemView本身就自带Context,你完全不用额外传递,直接用它就行:

修改MyViewHolder里的onClick方法:

override fun onClick(v: View) {
    // 从itemView获取Context
    val context = itemView.context
    // 替换成你要启动的目标Activity
    val intent = Intent(context, TargetActivity::class.java)
    // 如果需要传递Lead数据,记得先让Lead实现Parcelable/Serializable
    lead?.let {
        intent.putExtra(LEAD_KEY, it)
    }
    context.startActivity(intent)
}

这种方式不需要改动其他代码,直接就能用,非常省心。

解决方案2:把Context传入ViewHolder构造函数

如果你更习惯显式传递Context,可以修改ViewHolder的构造方法,在创建ViewHolder时把Adapter的Context传进去:

首先修改MyViewHolder的定义:

class MyViewHolder(v: View, private val context: Context) : RecyclerView.ViewHolder(v), View.OnClickListener {
    // ... 其他原有代码不变
    override fun onClick(v: View) {
        val intent = Intent(context, TargetActivity::class.java)
        lead?.let {
            intent.putExtra(LEAD_KEY, it)
        }
        context.startActivity(intent)
    }
}

然后在Adapter的onCreateViewHolder里传参:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val inflatedView = parent.inflate(R.layout.custom_lead_row, false)
    // 把Adapter的activity变量传进去
    return MyViewHolder(inflatedView, activity)
}

解决方案3:用接口回调(推荐的解耦方式)

如果想让Adapter和页面逻辑解耦(比如以后可能要改变点击后的行为),最好用接口回调的方式,把点击逻辑交给上层的Activity/Fragment处理:

第一步,在Adapter里定义点击回调接口:

class LeadListAdapter(
    context: Context, 
    private val leadList: List<Lead>,
    // 新增回调接口参数
    private val onLeadClickListener: OnLeadClickListener
) : RecyclerView.Adapter<LeadListAdapter.MyViewHolder>() {
    var activity:Context = context

    // 定义回调接口
    interface OnLeadClickListener {
        fun onLeadClicked(lead: Lead)
    }

    // ... 其他原有代码不变

    class MyViewHolder(v: View) : RecyclerView.ViewHolder(v), View.OnClickListener {
        // ... 其他原有代码不变
        override fun onClick(v: View) {
            lead?.let {
                // 调用回调接口,把点击事件抛给上层处理
                onLeadClickListener.onLeadClicked(it)
            }
        }
    }
}

第二步,在你的Activity里实现这个接口:

class YourActivity : AppCompatActivity(), LeadListAdapter.OnLeadClickListener {
    // ... 页面其他逻辑

    // 实现回调方法,在这里处理启动Activity的逻辑
    override fun onLeadClicked(lead: Lead) {
        val intent = Intent(this, TargetActivity::class.java)
        intent.putExtra(LeadListAdapter.LEAD_KEY, lead)
        startActivity(intent)
    }
}

第三步,创建Adapter时传入回调实例:

val adapter = LeadListAdapter(this, leadList, this)

这种方式让Adapter只负责列表展示,把业务逻辑交给上层组件,符合单一职责原则,后期维护更方便。

额外提醒

  • 如果你要通过Intent传递Lead对象,记得让Lead类实现Parcelable或者Serializable接口,不然会报错。
  • 你代码里的parent.inflate是Kotlin KTX的扩展方法,确保你的项目已经导入了对应的依赖哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 08:57:54