0

I have a RecycleView with a StaggeredGridLayoutManager. I add the views programatically in RecycleViewAdapter. The problem is that the layout of views use data binding :

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <data>

    <variable
      name="viewModel"
      type="com.myapp.myViewModel" />
  </data>

  <androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="vertical">
....

How can I set the viewModel to the views when I add them to recycleView?

This is my RecycleViewAdapter:

 class RecycleViewAdapter(context: Context, private val layouts: List<Int>) :
        RecyclerView.Adapter<RecycleViewAdapter.ViewHolder>() {
      override fun getItemCount(): Int {
        return layouts.size
      }

      private val mInflater: LayoutInflater = LayoutInflater.from(context)
      private var mClickListener: ItemClickListener? = null

      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = mInflater.inflate(R.layout.recycleview_row, parent, false)

        return ViewHolder(view)
      }

      override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val layout = layouts[position]
        val view = mInflater.inflate(layout, null)
        holder.layout.addView(view)
      }


      inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView),
          View.OnClickListener {
        internal val layout: LinearLayout = itemView.findViewById(R.id.layout)

        init {
          itemView.setOnClickListener(this)
        }

        override fun onClick(view: View) {
          if (mClickListener != null) mClickListener!!.onItemClick(view, adapterPosition)
        }
      }

      internal fun getItem(id: Int): Int {
        return layouts[id]
      }

      internal fun setClickListener(itemClickListener: ItemClickListener) {
        this.mClickListener = itemClickListener
      }

      interface ItemClickListener {
        fun onItemClick(view: View, position: Int)
      }
    }

My recycleview_row is :

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

  <data>

    <variable
      name="viewModel"
      type="com.myApp.BaseViewModel" />

  </data>

  <LinearLayout
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp">

  </LinearLayout>
</layout>

I include the layouts programatically into LinearLayout with id layout, and each viewModel extends BaseViewModel.

Gabrielle
  • 4,933
  • 13
  • 62
  • 122

1 Answers1

0

This is how we set ViewModel in dynamic Views.

  LayoutInflater lInflater = LayoutInflater.from(mContext);
      ItemListBinding itemBinding = ItemListBinding .inflate(lInflater, parent, false);
  itemBinding .setviewModel(viewModel);
  itemBinding.executePendingBindings();

Check this blog here

Deˣ
  • 4,191
  • 15
  • 24
  • Where should this be? what is ItemListBinding? – Gabrielle Jun 16 '19 at 18:53
  • This should be your xml layout name+ Binding . You need to write this in onBindViewHolder. Also you will need to send ViewModel instance to adapter. This code is written in Java . Please convert in Kotlin as it seems you are using that. – Deˣ Jun 16 '19 at 19:00
  • see my edited question. I tried with RecycleviewRowBinding and send added private val viewModels: List as a new parameter for adapter where I send the instances of viewModel for each view. On onBindViewHolder I added: val layout = layouts[position] val view = mInflater.inflate(layout, null) holder.layout.addView(view) binding.viewModel = viewModels[position] binding.executePendingBindings() but it is not working. What I am doing wrong? – Gabrielle Jun 16 '19 at 19:41
  • how can you have multiple viewmodels ? viewmodel is created per activity/fragment – Deˣ Jun 16 '19 at 19:46
  • You dont need to send ViewModel everywhere you can send the LiveData (List of DataSet) to adapter and in xml use that LiveData instead of ViewModel. Observe the liveData change in Activity/Fragment and notify the adapter in case of change. – Deˣ Jun 16 '19 at 19:49
  • I need to have many cards on recycleView and each card has it's own viewModel. – Gabrielle Jun 16 '19 at 19:53
  • I have added a blog link in the answer. Check. That should help you understand how it works. – Deˣ Jun 16 '19 at 19:55