Skip to content

Instantly share code, notes, and snippets.

@programmerr47
Created December 29, 2019 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save programmerr47/710f3bbbd1dd13cf7fbcb075e1c923fd to your computer and use it in GitHub Desktop.
Save programmerr47/710f3bbbd1dd13cf7fbcb075e1c923fd to your computer and use it in GitHub Desktop.
Base adapter that holds all delegates and differFactory for producing diffs
open class DelegatesAdapter<I : Any>(
private val differFactory: (RecyclerView.Adapter<*>) -> ListDiffer<I>,
vararg delegates: ItemDelegate<out I, *>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val delegatesIndexMap: Map<Class<*>, Int>
private val delegatesList: List<ItemDelegate<I, RecyclerView.ViewHolder>>
private val listDiffer: ListDiffer<I> by lazy { differFactory(this) }
val items: List<I> get() = listDiffer.currentList
constructor(vararg delegates: ItemDelegate<out I, *>): this({ SyncListDiffer(it) }, *delegates)
init {
val map = mutableMapOf<Class<*>, Int>()
delegates.forEachIndexed { index, delegate ->
if (map.put(delegate.itemType(), index) != null) {
throw IllegalArgumentException()
}
}
delegatesIndexMap = map
delegatesList = delegates.map {
@Suppress("UNCHECKED_CAST")
it as? ItemDelegate<I, RecyclerView.ViewHolder>
?: throw IllegalArgumentException()
}
}
override fun getItemViewType(position: Int): Int = delegatesIndexMap[items[position]::class.java]
?: throw IllegalStateException("There is no delegate for item with type: ${items[position]::class.java}")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = delegatesList[viewType].createVewHolder(parent)
override fun getItemCount() = items.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
delegatesList[getItemViewType(position)].bindView(position, items[position], holder)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads)
} else {
delegatesList[getItemViewType(position)].bindView(position, items[position], holder, payloads)
}
}
fun updateItem(old: I, new: I) {
val newList = items.toMutableList()
if (newList.updateFirst(new, { it == old })) {
submitList(newList)
}
}
fun submitList(list: List<I>) = listDiffer.submitList(list)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment