Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement ViewHolder using sealed class in Kotlin

I saw an interesting viewholder implementation in this tweet https://twitter.com/AndroidDev/status/972502799496790018

override fun onBindViewHolder(holder: SealedAdapterViewHolder, position: Int) {
  return when (holder) {
    is HeaderHolder -> holder.displayHeader(items[position])
    is DetailsHolder -> holder.displayDetails(items[position])
  }
}

Unfortunately i can't figure out how to implement thouse holders. And I didn't find any examples of this trick.

In my viewholders I have to extend RecyclerView.ViewHolder and I have to extend sealed class so i can use it in "when clauses". Multiple inharitance is not allowed.

So is it possible and if it is then how?

P.S.

original authors write this:

You can also use sealed classes in a RecyclerView adapter. They’re a perfect fit for ViewHolders - with a clean set of types to dispatch explicitly to each holder. Used as an expression, the compiler will error if all types aren’t matched.

like image 286
Maksim Turaev Avatar asked Mar 12 '18 12:03

Maksim Turaev


People also ask

How do you use sealed classes in Kotlin?

Sealed class rulesSealed classes cannot be instantiated directly. Sealed classes cannot have public constructors (The constructors are private by default). Sealed classes can have subclasses, but they must either be in the same file or nested inside of the sealed class declaration.

Can we inherit sealed class in Kotlin?

Kotlin has a great feature called sealed class, which allow us to extend an abstract class in a set of fixed concrete types defined in the same compilation unit (a file). In other words, is not possible to inherit from the abstract class without touching the file where it is defined.

Can sealed classes be instantiated?

A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.

What is ViewHolder in Kotlin?

The purpose of the viewholder pattern is to only make the expensive findViewById calls once for every view, and then hold those references inside the ViewHolder , and access the views from there whenever you need to bind one.


2 Answers

Something like this:

sealed class SealedAdapterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    class HeaderHolder(view: View) : SealedAdapterViewHolder(view)

    class DetailsHolder(view: View) : SealedAdapterViewHolder(view)
}
like image 166
veritas1 Avatar answered Oct 17 '22 19:10

veritas1


it's in the first post of the thread.

fun foo(holder : SealedAdapterViewHolder){
    when (holder) {
       is HeaderHolder -> holder.displayHeader(items[position])
       is DetailsHolder -> holder.displayDetails(items[position])
    }
}

sealed class SealedAdapterViewHolder(view: View) : RecyclerView.ViewHolder(view)
data class HeaderHolder(val view: View): SealedAdapterViewHolder(view){
    fun displayHeader(...){}
}
data class DetailsHolder(val view: View): SealedAdapterViewHolder(view){
    fun displayDetails(...){}
}
like image 32
leonardkraemer Avatar answered Oct 17 '22 21:10

leonardkraemer