0

I'm trying to create a RecyclerView that having checkbox in each of its item. I followed this link to save states of checkbox, that is to add a boolean variable to my object. However, I encountered a problem that the value of isChecked from my object cannot be changed. Is the content of currentList immutable? Is there any way for me to implement this feature with ListAdapter?

Here is the snippet of my code. Thank you very much.

class DocumentAdapter() : ListAdapter<Document, DocumentAdapter.DocumentViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DocumentViewHolder {
        return LayoutInflater.from(parent.context)
            .inflate(R.layout.item_document, parent, false)
            .let {
                DocumentViewHolder(it)
            }
    }

    override fun onBindViewHolder(holder: VH, position: Int) {
        holder.bind(getItem(position))
    }

    class DocumentViewHolder(
        override val view: View
    ) : RecyclerView.ViewHolder<DocumentDTO>(view) {

        fun bind(item: Document) {
            cbItem.isChecked = item.isChecked
            cbItem.setOnCheckedChangeListener { _, isChecked ->
                item.isChecked = isChecked // Not working
            }
        }
    }
}

When debugging, after running through the line item.isChecked = isChecked, I can see value isChecked inside currentList is not updated, even though that value of the local Document item has been updated.

Hellious
  • 180
  • 9

2 Answers2

0

It's not that the content of a ListAdapter is immutable, it's that, from what I see in your code snippet, that the Document's isChecked variable is immutable.

The Document object itself should be able to hold stateful data of the current item that needs to be displayed. If you are not able to tweak the Document object itself, I would either create a DocumentWrapper object that allows you to create an initial and mutable checked state.

class DocWrapper(val document: Document) {
  var isChecked = document.isChecked
}

You can map your data before submitting to your ListAdapter

val docList = List<Document>()
val docWrapperList: List<DocWrapper> = docList.map { DocWrapper(it) }
PenguinDan
  • 904
  • 7
  • 15
  • Hi, I'm pretty sure I have set `isChecked` as `var`. However, when debugging, after running through the line `item.isChecked = isChecked`, I can see value `isChecked` inside currentList is not updated. Even though the local `Document` item has been updated. Do you have any thoughts about this? – Hellious Jun 17 '20 at 08:58
0

Since mutation to content of ListAdapter must be submitted through submitList(), I have to create a callback and send the updated item out to update the data.

    fun bind(item: Document) {
        cbItem.isChecked = item.isChecked
        cbItem.setOnCheckedChangeListener { _, isChecked ->
            item.isChecked = isChecked
            onCheckBoxClicked(item, isChecked)
        }
    }
Hellious
  • 180
  • 9