使用DataBinding时如何在RecyclerView.Adapter中绑定ViewModel
解决方案
核心逻辑:SongDetailViewModel的生命周期与承载它的Fragment/Activity绑定,不建议在Adapter中直接初始化,直接从宿主层传入已初始化的实例即可,操作步骤如下:
步骤1:修改Adapter构造函数,接收ViewModel实例
修改SongAdapter.kt代码,把ViewModel作为构造参数传入:
class SongAdapter( // 新增构造参数接收宿主传入的ViewModel private val songDetailViewModel: SongDetailViewModel ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { inner class ViewHolderSong(private val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener { private fun bindSong(song: Song) { binding as SongItemBinding binding.apply { this.song = song // 直接用构造参数传入的ViewModel赋值即可 this.viewModel = songDetailViewModel executePendingBindings() rootLyt.setOnClickListener(this@ViewHolderSong) icMore.setOnClickListener(this@ViewHolderSong) } } } }
步骤2:在Fragment中初始化Adapter时传入ViewModel
你已经在Fragment中通过by viewModels()拿到了ViewModel实例,创建Adapter的时候直接传入即可:
// Fragment内部代码 private val viewModel: SongDetailViewModel by viewModels() // 初始化Adapter时传入当前的ViewModel实例 private val songAdapter = SongAdapter(viewModel)
注意事项
- 不要在Adapter内部单独初始化ViewModel,否则会拿到和宿主完全独立的新实例,无法实现数据联动
- 该方案下Adapter、ViewModel的生命周期都与宿主Fragment对齐,不会出现内存泄漏问题
- 如果你的Adapter需要跨业务复用,可以把ViewModel相关逻辑抽为公共接口,避免直接依赖具体的ViewModel类
内容的提问来源于stack exchange,提问作者Ibramazin
相关产品推荐
相关产品推荐

