TLDR;
Хорошо, вот код, который должен работать:
class HomePageRecylerAdapter(private val data: ArrayList<Any>) : RecyclerView.Adapter<BaseViewHolder<Any>>() {
companion object {
const val typeCarousel = 0
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<Any> {
return when (viewType) {
typeCarousel -> {
val view =
LayoutInflater.from(parent.context).inflate(0, parent, false)
CarouselViewHolder(view) as BaseViewHolder<Any>
}
else -> throw IllegalArgumentException("Invalid view type")
}
}
override fun getItemCount() = data.size
override fun onBindViewHolder(holder: BaseViewHolder<Any>, position: Int) {
val element = data[position]
when (element) {
is HomeCarousel -> {
holder.bind(element)
}
else -> IllegalArgumentException("Invalid binding")
}
}
override fun getItemViewType(position: Int): Int {
val element = data[position]
return when (element) {
is HomeCarousel -> typeCarousel
else -> throw IllegalArgumentException("Invalid type of data {$position}")
}
}
inner class CarouselViewHolder(itemView: View) : BaseViewHolder<HomeCarousel>(itemView) {
override fun bind(item: HomeCarousel) {
}
}
}
abstract class BaseViewHolder<in T: Any>(itemView: View) :
RecyclerView.ViewHolder(itemView) {
abstract fun bind(item: T)
}
Объяснение
Возможно, этот ответ может помочь вам получить больше идей - https://stackoverflow.com/a/51110484/2674983
Хотя я нахожу обоснование в ответе неверным.Проблема не в том, что адаптер написан на Java, а в том, что он требует возврата как подтипа viewholder, так и его аргумента.В противном случае было бы легко использовать что-то вроде use-site variance .
Я думаю, что правильным способом решения этой проблемы было бы использование контравариантности:
abstract class BaseViewHolder<in T>(itemView: View) :
RecyclerView.ViewHolder(itemView) {
abstract fun bind(item: T)
}
Это потому, что объект типа T может быть чем угодно и ему нужно передать сеттеру, поэтому нам нужно только установить это в ViewHolder.Тем не менее, у контрапозитива есть интересный поворот ... подтип работает сейчас в противоположном направлении!Итак, теперь BaseViewHolder<HomeCarousel>
больше не является подтипом BaseViewHolder<Any>
, поскольку подтип перевернут.
Чтобы исправить это, мы могли бы выполнить «небезопасное приведение», как я делал в коде.
О, а использование BaseViewHolder<*>
(проекция в виде звезды) действительно решает проблемы с подтипами,поскольку каждый экземпляр BaseViewHolder теперь является подтипом, но он накладывает ограничения как ковариации, так и контравариантности, поэтому здесь это бесполезно.