Skip to content

Instantly share code, notes, and snippets.

@segunfamisa
Created September 26, 2019 09:11

Revisions

  1. segunfamisa created this gist Sep 26, 2019.
    56 changes: 56 additions & 0 deletions AdapterObservableListItem.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    class ObservableListField<T, VH : RecyclerView.ViewHolder>(
    private val adapter: RecyclerView.Adapter<VH>,
    private val diffUtilCallbackProducer: ((List<T>, List<T>) -> DiffUtil.Callback)?,
    initialValue: List<T>
    ) : ObservableProperty<List<T>>(initialValue = initialValue) {

    private var result: DiffUtil.DiffResult? = null

    override fun beforeChange(
    property: KProperty<*>,
    oldValue: List<T>,
    newValue: List<T>
    ): Boolean {
    val diffUtilCallback = diffUtilCallbackProducer?.invoke(oldValue, newValue) ?: SimpleDiffUtilCallback(
    oldItems = oldValue,
    newItems = newValue
    )
    result = DiffUtil.calculateDiff(diffUtilCallback)
    return true
    }

    override fun afterChange(property: KProperty<*>, oldValue: List<T>, newValue: List<T>) {
    result?.dispatchUpdatesTo(adapter)
    super.afterChange(property, oldValue, newValue)
    }

    /**
    * Very simple diff util callback
    */
    private inner class SimpleDiffUtilCallback<T> constructor(
    private val oldItems: List<T>,
    private val newItems: List<T>
    ) :
    DiffUtil.Callback() {
    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
    oldItems[oldItemPosition] == newItems[newItemPosition]

    override fun getOldListSize(): Int = oldItems.size

    override fun getNewListSize(): Int = newItems.size

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
    oldItems[oldItemPosition] == newItems[newItemPosition]
    }
    }

    fun <T, VH : RecyclerView.ViewHolder> RecyclerView.Adapter<VH>.observableList(
    initialValue: List<T>,
    diffUtilCallbackProducer: ((List<T>, List<T>) -> DiffUtil.Callback)? = null
    ): ObservableProperty<List<T>> {
    return ObservableListField(
    adapter = this,
    diffUtilCallbackProducer = diffUtilCallbackProducer,
    initialValue = initialValue
    )
    }