How to Bind viewModel in adapter while using databinding

Viewed 781

song_item.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
    <variable
        name="song"
        type=".models.Song" />

    <variable
        name="viewModel"
        type=".SongDetailViewModel" />
  </data>

  <TextView
   android:id="@+id/txt_song_name"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"     
   app:selected="@{safeUnbox(viewModel.currentData.id == song.id)}"
   />

</layout>

SongAdapter.kt

I am looking for a way to bind the viewModel in song_item to my adapter.

  • I will need to initialise SongDetailViewModel.

  • In fragment I could do:

    private val viewModel: SongDetailViewModel by viewModels()

But How will I do in that in my adapter:

class SongAdapter(
) : 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
            this.viewModel = songDetailViewModel <--- here, I don't know how to initialize this viewModel inside the adapter
            executePendingBindings()
            rootLyt.setOnClickListener(this@ViewHolderSong)
            icMore.setOnClickListener(this@ViewHolderSong)
        }
    }
   }
  }
1 Answers

You should send viewModel created in fragment to SongAdapter as a parameter. After that, you can bind it to song_item.

Also don't forget to set lifecycleOwner to your song item binding for correct observing of changes. You should send it also by parameter to SongAdapter.

Your SongAdapter should look at the end of the day like this:

class SongAdapter(
    private val viewModel: SongDetailViewModel,
    private val lifecycleOwner: LifecycleOwner
) : 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
                this.viewModel = viewModel
                this.lifecycleOwner = lifecycleOwner
                executePendingBindings()
                rootLyt.setOnClickListener(this@ViewHolderSong)
                icMore.setOnClickListener(this@ViewHolderSong)
            }
        }
    }
}
Related