Skip to content

Instantly share code, notes, and snippets.

@alwarren
Last active April 9, 2018 16:21
Show Gist options
  • Save alwarren/97c5f97300fb24a26c4f7f8dbd71ec93 to your computer and use it in GitHub Desktop.
Save alwarren/97c5f97300fb24a26c4f7f8dbd71ec93 to your computer and use it in GitHub Desktop.
Using DiffUtil in Android RecyclerView
// See https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00
fun <T> RecyclerView.Adapter<*>.autoNotify(oldList: List<T>, newList: List<T>, compare: (T, T) -> Boolean) {
val diff = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return compare(oldList[oldItemPosition], newList[newItemPosition])
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
})
diff.dispatchUpdatesTo(this)
}
class ItemRecyclerAdapter : RecyclerView.Adapter<ItemRecyclerAdapter.ItemHolder>() {
var items: List<Item> by Delegates.observable(emptyList()) {
_, old, new ->
autoNotify(old, new) {
o, n -> o.id == n.id
&& o.name == n.name
&& o.thumb == n.thumb
}
}
override fun getItemCount(): Int {
return items.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
// see Extensions.kt
val inflatedView = parent.inflate(R.layout.card_row, false)
return ItemHolder(inflatedView)
}
override fun onBindViewHolder(holder: ItemHolder?, position: Int) {
val item = items[position]
// ...
}
class ItemHolder(view: View) : RecyclerView.ViewHolder(view) {
// ...
}
}
class MainActivity : DaggerAppCompatActivity() {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
// ..,.
initAdapter()
initViewModel()
// ...
}
private fun initAdapter() {
adapter = ItemRecyclerAdapter()
linearLayoutManager = LinearLayoutManager(this)
item_list.layoutManager = linearLayoutManager
item_list.adapter = adapter
}
private fun initViewModel() {
viewModel.getItems().observe(this, Observer {
it?.let { data -> updateUI(data) }
})
}
private fun updateUI(response: ItemsResponse) {
var items = listOf(Item(name="Empty List"))
when(response) {
is ItemsResponse.Success -> {
if (!response.items.isEmpty()) {
items = response.items
}
}
is ItemsResponse.Error -> {
Log.d(TAG, response.error)
items = listOf(Item(name="Unknown Error"))
}
}
adapter.items = items
}
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment