Search code examples
androidkotlinandroid-recyclerviewkotlin-extension

Generics for RecyclerView.Adapter Android


I am trying to use a common extension function for all RecyclerView.Adapter in my app so I created an ext fun called notifyAdapter, But it is not working as expected.

fun <T> RecyclerView.Adapter<RecyclerView.ViewHolder>.notifyAdapter() {
    updateAll()
    notifyDataSetChanged()
}

When i use

offlineListAdapter.notifyAdapter() or onlineListAdapter.notifyAdapter()

it throws

Cannot be applied to receiver OfflineListAdapter

OfflineListAdapter.kt

    class OfflineListAdapter : RecyclerView.Adapter<OfflineListAdapter.OfflineListHolder>() {

      class OfflineListHolder(view: View) : RecyclerView.ViewHolder(view) {

      }
    }

How can I create a common extension function for all RecyclerView.Adapter using Generics.

Thanks in advance.


Solution

  • There are a couple ways to do this.

    1. You can mark the ViewHolder parameter with out variance. This way your function isn't generic, so you won't have access to the exact type of the ViewHolder in it.

      fun RecyclerView.Adapter<out RecyclerView.ViewHolder>.notifyAdapter() {  ...  }
      
    2. Alternatively, you can have a generic type parameter for the function that's bound to be a subclass of ViewHolder. This way you can use T inside the function, for example, you could create a listOf<T>() if you wanted to.

      fun <T : RecyclerView.ViewHolder> RecyclerView.Adapter<T>.notifyAdapter() {  ...  }
      
    3. Finally, you could also use star projection, which I believe in this case will give you the exact same result as the first solution, since the type argument of the Adapter class has an upper bound of ViewHolder.

      fun RecyclerView.Adapter<*>.notifyAdapter() {  ...  }
      

    You can read in more detail about variance and projections in the offical documentation here.