Home > Software engineering >  notifyOnDataSetChanged() in kotlin
notifyOnDataSetChanged() in kotlin

Time:12-05

I'm studying kotlin for android for a few months and I have one question for a while

private fun configRecoverReservations(){
    val dialog: AlertDialog? = SpotsDialog.Builder()
        .setContext(requireContext())
        .setMessage(getString(R.string.recovering_reservations))
        .setCancelable(false)
        .build()
    dialog?.show()
    adUserRef = FirebaseDatabase.getInstance()
        .getReference("Reservations")
        .child(auth.currentUser!!.uid)
    adUserRef.addValueEventListener(object: ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            reservationList.clear()
            for (ds: DataSnapshot in snapshot.children){
                reservationList.add(ds.getValue(Reservation::class.java)!!)
            }
            if(reservationList.isEmpty()) {
                binding.recyclerMyReservations.hide()
                binding.textEmptyList.show()
            }
            reservationList.reverse()
            dialog?.dismiss()
            adapterReservations.notifyDataSetChanged()
        }

        override fun onCancelled(error: DatabaseError) {
            null
        }
    })
}

How would be the fanciest way to change the notifyOnDataSetChanged() in this situation, since it's not the best solution, as Google says? here It says:

˜Notify any registered observers that the data set has changed.

There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred. Structural changes are when items are inserted, removed or moved within the data set.

This event does not specify what about the data set has changed, forcing any observers to assume that all existing items and structure may no longer be valid. LayoutManagers will be forced to fully rebind and relayout all visible views.

RecyclerView will attempt to synthesize visible structural change events for adapters that report that they have stable IDs when this method is used. This can help for the purposes of animation and visual object persistence but individual item views will still need to be rebound and relaid out.

If you are writing an adapter it will always be more efficient to use the more specific change events if you can. Rely on notifyDataSetChanged() as a last resort."

CodePudding user response:

Currently its recommended to use ListAdapter for handling dynmamic data in RecyclerView . It is a wrapper of the existing RecyclerView Adapter. It uses Diff check Util to check whether the content are same. So if the content is same for two items, it will not redraw the view again. It only redraws when no existing drawn views matches the current view data. So it will give the same performance of the RecyclerView Adapter.

No need to call notifyDataSetChanged() here in ListAdapter, which is a costlier operation.

When there is a change in list , you need to call adapter.submitList(yourList) . You can call this in your addValueEventListener.

While creating adapter in activity/fragment, you need to pass your ItemDiff object in adapter constructor.

Or you can directly create object while calling ListAdapter constructor, like this.

 class RecyclerListAdapter() : ListAdapter<MyModelClass, MyViewHolder>(ItemDiff()){
//Adapter
}

Adapter class:

class RecyclerListAdapter(
    itemDiff: ItemDiff
) : ListAdapter<MyModelClass, MyViewHolder>(itemDiff) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        return MyViewHolder(
        )
    }


    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {

    }

     class ItemDiff : DiffUtil.ItemCallback<MyModelClass>() {
        override fun areItemsTheSame(oldItem: MyModelClass, newItem: MyModelClass): Boolean {
            return oldItem.uuid == newItem.uuid
        }

        override fun areContentsTheSame(
            oldItem: MyModelClass,
            newItem: MyModelClass
        ): Boolean {
            return oldItem.id == newItem.id &&
                    oldItem.name == newItem.name &&
        }
    }
}
  • Related