简体   繁体   中英

How do I get the difference between old and new data using Delegates.Observable?

Wouldn't it be better to get the difference instead of returning the whole values for the UI to redraw?

var collection: List<String> by 
Delegates.observable(emptyList()) { prop, old, new ->
    notifyDataSetChanged()    
}

is it possible to make it more efficient?

You should take a look to DiffUtil class

DiffUtil is a utility class that can calculate the difference between two lists and output a list of update operations that converts the first list into the second one.

DiffUtil uses Eugene W. Myers's difference algorithm to calculate the minimal number of updates to convert one list into another. Myers's algorithm does not handle items that are moved so DiffUtil runs a second pass on the result to detect items that were moved.

If the lists are large, this operation may take significant time so you are advised to run this on a background thread,

Basically, you have to implement a DiffUtil.Callback using both lists,

data class MyPojo(val id: Long, val name: String)

class DiffCallback(
        private val oldList: List<MyPojo>,
        private val newList: List<MyPojo>
) : DiffUtil.Callback() {

    override fun getOldListSize() = oldList.size

    override fun getNewListSize() = newList.size

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldList[oldItemPosition].id == newList[newItemPosition].id
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldList[oldItemPosition].name == newList[newItemPosition].name
    }

    override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
        // Implement method if you're going to use ItemAnimator
        return super.getChangePayload(oldItemPosition, newItemPosition)
    }
}

then you have to notify the adapter using it. for example, you could create a function in your adapter like this:

fun swap(items: List<myPojo>) {
    val diffCallback = ActorDiffCallback(this.items, items)
    val diffResult = DiffUtil.calculateDiff(diffCallback)

    this.items.clear()
    this.items.addAll(items)
    diffResult.dispatchUpdatesTo(this)
}

In your case , supposing that collection is a member of your adapter:

var collection: List<String> by Delegates.observable(emptyList()) { prop, old, new ->
    val diffCallback = DiffCallback(old, new)
    val diffResult = DiffUtil.calculateDiff(diffCallback)
    diffResult.dispatchUpdatesTo(this)
}

Some references:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM