Generic RecyclerViewAdapter

bigyan4424

Bigyan Thapa

Posted on December 24, 2019

Generic RecyclerViewAdapter
Trying to make one adapter fit all RecyclerViews in the application.

While this is not an absolute use-case as we might want different list to behave differently. But the core purpose of RecyclerView is to display the data and be able to scroll through it. Also, when we click on the list-item we possible want to navigate to details for that list-item. While doing this, there will be a lot of redundant code that will be duplicated in all RecyclerView adapters in our codebase.

Below is a basic example of abstracting away the core functionality of a RecyclerView adapter and have the sub-classes take care of the rest. This articles assumes that the readers will have basic understanding of RecyclerView, databinding and kotlin.

abstract class BaseRecyclerViewAdapter<T> : Adapter<ViewHolder>(), {

  var items: List<T> = emptyList()
    set(value) {
      field = value
      notifyDataSetChanged()
    }

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = getViewHolder(parent, viewType)

  override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    if(position in items.indices) {
      (holder as Binder<T>).bind(items[position])
    }

  abstract fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder

  interface Binder<in T> {
    fun bind(item: T)
  }
}

Usage

The above abstract RecyclerView adapter can be used in a fragment as follows:

class SomeListFragment {

  private lateinit var adapter: SomeAdapter

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) : View? {
    super.onCreateView(inflater, container, savedInstanceState)
    // initialization code here ...
    adapter = SomeAdapter() // initialize adapter here
    // ...
  }

  // rest of fragment implementation

  inner class SomeAdapter : BaseRecyclerViewAdapter<SomeData>() {
    override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
      val viewBinding: SomeListItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.some_list_item, parent, false)
      return SomeViewHolder(viewBinding)
    }
  }

  inner class SomeViewHolder(private val viewBinding: SomeListItemBinding) : ViewHolder(viewBinding.root), BaseRecyclerViewAdapter.Binder<SomeData> {

   override fun bind(item: SomeData) {
     /*
       bind data here, we can also assign click listeners
       viewBinding.root.setOnClickListener { ... }
     */
   }
  }
}

Please provide feedback in comments.
Thank you for reading.

💖 💪 🙅 🚩
bigyan4424
Bigyan Thapa

Posted on December 24, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Generic RecyclerViewAdapter
android Generic RecyclerViewAdapter

December 24, 2019