在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:
- 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 }
- 调整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的存在,耦合度更低、可复用性更高:
- 调整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]) } } // 其他原有逻辑保持不变 }
- 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
相关产品推荐
相关产品推荐

