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

在RecyclerView的Adapter中访问ViewModel报Activity未附加异常如何解决

问题原因

触发该异常的核心原因是:你在Adapter中通过传入的Activity实例获取ViewModel时,对应的Activity还未完成onCreate生命周期回调,尚未和Application实例完成绑定,不符合ViewModel的获取时机要求。
同时直接将Activity实例传入Adapter的写法存在内存泄漏风险,也不符合关注点分离的开发原则,Adapter不需要持有Activity的引用。

解决方案

推荐以下两种更合理的实现方式,按需选择即可:

方案1:直接将ViewModel实例传入Adapter

在Activity的onCreate生命周期中完成ViewModel初始化后,直接将实例传入Adapter,避免Adapter自己通过Activity获取ViewModel:

  1. Activity侧初始化代码:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 先完成ViewModel初始化
    val foodViewModel = ViewModelProvider(this)[FoodViewModel::class.java]
    // 初始化Adapter时传入ViewModel实例
    val adapter = FoodInSortAdapter(foodViewModel, 你的列表数据)
    recyclerView.adapter = adapter
}
  1. 调整Adapter构造逻辑:
class FoodInSortAdapter(
    val viewModel : FoodViewModel,
    private val list: List<String>
): RecyclerView.Adapter<FoodInSortAdapter.Holder>() {

    // 删除原有通过Activity获取ViewModel的lazy属性代码
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.sortitem, parent, false)
        return Holder(view)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.sortName.text = list[position]
        holder.itemView.setOnClickListener {
            val m=list[position]
            viewModel.setQuery(m)
        }
    }
    // 其他原有逻辑保持不变
}

方案2:通过点击回调解耦(更推荐)

将列表点击事件抛给Activity处理,Adapter完全不感知ViewModel的存在,耦合度更低、可复用性更高:

  1. 调整Adapter构造逻辑:
class FoodInSortAdapter(
    private val list: List<String>,
    // 新增点击回调函数参数
    private val onItemClick: (String) -> Unit
): RecyclerView.Adapter<FoodInSortAdapter.Holder>() {

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

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.sortName.text = list[position]
        holder.itemView.setOnClickListener {
            // 触发回调,将选中的内容抛给外部处理
            onItemClick(list[position])
        }
    }
    // 其他原有逻辑保持不变
}
  1. Activity侧初始化代码:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val foodViewModel = ViewModelProvider(this)[FoodViewModel::class.java]
    // 初始化Adapter时传入点击回调实现
    val adapter = FoodInSortAdapter(你的列表数据) { selectedName ->
        foodViewModel.setQuery(selectedName)
    }
    recyclerView.adapter = adapter
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:18:01