Android DiffUtil and ListAdapter for RecyclerView list item updates

recyclerview dependency, the minimum support library is 27.

implementation "com.android.support:recyclerview-v7:27.1.0"

ListItem.kt, the data to be displayed in the recyclerview.

data class ListItem(var text : String, var clicks : Int = 0)

ItemArrayAdapter.kt, the implementation of the ListAdapter and DiffUtil for the recyclerview.

import android.support.v7.recyclerview.extensions.ListAdapter
import android.support.v7.util.DiffUtil
import android.support.v7.widget.RecyclerView
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import kotlinx.android.synthetic.main.list_item.view.*

class ItemArrayAdapter(private val listItemClickListener: ListItemClickListener)
    : ListAdapter(ListItemCallback()) {

    class ListItemCallback : DiffUtil.ItemCallback() {
        override fun areItemsTheSame(oldItem: ListItem, newItem: ListItem): Boolean {
            return oldItem == newItem
        }

        override fun areContentsTheSame(oldItem: ListItem, newItem: ListItem): Boolean {
            return oldItem.text == newItem.text && oldItem.clicks == newItem.clicks
        }
    }

    interface ListItemClickListener {
        fun onItemClick(listItem : ListItem, position : Int)
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = getItem(position)
        (holder as ListenItemViewHolder).bind(item, position)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
        return ListenItemViewHolder(view)
    }

    inner class ListenItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var tvContent: TextView = itemView.tv_content
        var tvClickCount: TextView = itemView.tv_click_counts

        fun bind(listItem : ListItem, position : Int) {
            tvContent.text = listItem.text

            if (listItem.clicks > 0) {
                tvClickCount.text = "" + listItem.clicks
            } else {
                tvClickCount.text = ""
            }

            itemView.setOnClickListener {
                listItemClickListener.onItemClick(listItem, position)
            }
            Log.d("onclick", "onClick " + position + " " + tvContent.text)
        }
    }
}

MainActivity.kt, the main activity which initializes the recyclerview. when updating a new list, just call itemArrayAdapter.submitList(itemList)

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*

class MainActivity : AppCompatActivity(), ItemArrayAdapter.ListItemClickListener {
    private val itemList = ArrayList()
    private lateinit var itemArrayAdapter : ItemArrayAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        itemArrayAdapter = ItemArrayAdapter(this)
        rv_list.layoutManager = LinearLayoutManager(this)
        rv_list.itemAnimator = DefaultItemAnimator()
        rv_list.adapter = itemArrayAdapter
        (0..99).mapTo(itemList) { ListItem("Item " + it) }
        itemArrayAdapter.submitList(itemList)

        btn_refresh.setOnClickListener {
            val newItemList = ArrayList()
            (0..Random().nextInt(100)).mapTo(newItemList) { ListItem("Item ${randomStr()} $it") }
            itemArrayAdapter.submitList(newItemList)
        }
    }

    override fun onItemClick(listItem: ListItem, position: Int) {
        itemList[position].clicks++

        val newItemList = ArrayList()
        itemList.forEach {
            newItemList.add(ListItem(it.text, it.clicks))
        }
        itemArrayAdapter.submitList(newItemList)
    }

    private fun randomStr() : String {
        val r = Random()
        return java.lang.Long.toString(r.nextLong() and java.lang.Long.MAX_VALUE, 36)
    }
}

list_item.xml, the layout for the list item in the recyclerview.



    
    

activity_main.xml, the layout for the main activity.



    

Complete example in Github

Search within Codexpedia

Custom Search

Search the entire web

Custom Search