Home > front end >  How to update the data passed to the adapter without recreating it android kotlin
How to update the data passed to the adapter without recreating it android kotlin

Time:02-02

Faced such a problem: I have a RecyclerView, the data for which I get from the ViewModel using StateFlow:

viewModel.items.collect {
    setRecyclerView(items)
}

Then, let's say, somewhere inside the Fragment, I change the data for items and there are more of them. In order for my RecyclerView to see my changes, I have to call the setRecyclerView(items) function again, which, it seems to me, can lead to the most unexpected consequences (for example, items will be duplicated). The question is: is it possible to somehow change the data and update the RecyclerView (including the onBindViewHolder function in it) without yet another creation of an Adapter?

CodePudding user response:

Let's start talking about the adapter implementation. Reading your question, I believe you used RecyclerView.Adapter to implement your adapter. But there is another option that is simpler and more performant than this. It's the ListAdapter:

The most interesting thing about ListAdapter is the DiffUtil, that have a performative way to check if any item on your list was updated, deleted, or included. Here's a sample of the implementation:

abstract class MyAdapter: ListAdapter<ItemModel, MyAdapter.MyViewHolder>(DIFF_CALLBACK) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val binding = ItemSimplePosterBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return MyViewHolder(binding)
    }

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

    class MyViewHolder(
        private val binding: ItemSimplePosterBinding
    ): RecyclerView.ViewHolder(binding.root) {

        fun bind(item: ItemModel) {
            // Here you can get the item values to put these values on your view
        }

    }

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<ItemModel>() {
            override fun areItemsTheSame(oldItem: ItemModel, newItem: ItemModel): Boolean {
                // need a unique identifier to have sure they are the same item. could be a comparison of ids. In this case, that is just a list of strings just compares like this below
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: ItemModel, newItem: ItemModel): Boolean {
                // compare the objects
                return oldItem == newItem
            }

        }
    }
}

So, when your list is updated, you just have to call the submitList from the adapter, like this:

viewModel.items.collectLatest { items ->
     // You will send the items to your adapter here
     adapter.submitList(items)
}

Then, your RecyclerView just has to be configured on onViewCreated for example, and your list can be defined and updated in another place, observing the items change from ViewModel.

  • Related