0

I implemented ListAdapter, that T is sealed class ViewHolderModel. Then, I trying to implement DiffUtil.ItemCallback to be used Adapter, but I faced a problem.

ViewHolderModel included various data objects, they are unique id of some objects are ambiguous.

How can I implement efficient ItemCallback?

ViewHolderModel (sealed class)

sealed class ViewHolderModel {
    object Error : ViewHolderModel()
    object Footer : ViewHolderModel()

    data class Header(
        val title: String,
        val description: String,
        ...
    ) : ViewHolderModel()

    sealed class Item : ViewHolderModel() {
        abstract val id: Long
        abstract val thumbnail: String

        data class Image(
            override val id: Long,
            override val thumbnail: String
            ...
        ) : Item()

        data class Video(
            override val id: Long,
            override val thumbnail: String
            ...
        ) : Item()

        data class Sound(
            override val id: Long,
            override val thumbnail: String
            ...
        ) : Item()
    }
}

ItemCallback

companion object {
    val Comparator by lazy {
        object : DiffUtil.ItemCallback<ViewHolderModel>() {
            override fun areItemsTheSame(oldItem: ViewHolderModel, newItem: ViewHolderModel): Boolean =
                ???
    
            override fun areContentsTheSame(
                oldItem: ViewHolderModel,
                newItem: ViewHolderModel
            ): Boolean = oldItem == newItem
        }
    }
}

I tried to add abstract field(id) to ViewHolderModel as below but isn't look good. Is there a better way than this?

sealed class ViewHolderModel {
    abstract val id : Long
    object Error : ViewHolderModel() {
        override val id: Long
            get() = Long.MIN_VALUE
    }

    object Footer : ViewHolderModel() {
        override val id: Long
            get() = Long.MIN_VALUE + 1
    }
    ...

// in ItemCallback
override fun areItemsTheSame(oldItem: ViewHolderModel, newItem: ViewHolderModel): Boolean =
                oldItem.id == newItem.id
Ethan Choi
  • 2,339
  • 18
  • 28

1 Answers1

1

Depends on how unique your data is. Of course it would be better if you have some unique identifiers, but maybe your Header's title is already unique and already content of description can change? That way you could use sth like following (you can go deeper inside Item to distinguish between Image Video & Sound if you like)

override fun areItemsTheSame(
    oldItem: ViewHolderModel,
    newItem: ViewHolderModel
): Boolean = when {
    oldItem is ViewHolderModel.Header && newItem is ViewHolderModel.Header && oldItem.title == newItem.title -> true
    oldItem is ViewHolderModel.Item && newItem is ViewHolderModel.Item && oldItem.id == newItem.id -> true
    else -> false
}
            
thehrlein
  • 133
  • 1
  • 4