Skip to content

Instantly share code, notes, and snippets.

@Ghedeon
Created December 25, 2019 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ghedeon/48d214ccbb7a48a4745f9d9540e164d1 to your computer and use it in GitHub Desktop.
Save Ghedeon/48d214ccbb7a48a4745f9d9540e164d1 to your computer and use it in GitHub Desktop.
Multitype RecyclerView Adapter
recycler_view.withBindings {
+DateBinding()
+IncomingMessageBinding()
+OutgoingMessageBinding()
}
recycler_view.submitList(listOf<Widget.State>(...))
//**************************************************************//
class DateBinding : ItemBinding<DateWidget.State, DateWidget> {
override fun onCreateView(context: Context) = DateWidget(context)
override fun onBindView(view: DateWidget, item: DateWidget.State) {
view.render(item)
}
}
class IncomingMessageBinding : ItemBinding<IncomingMessageWidget.State, IncomingMessageWidget> {
override fun onCreateView(context: Context): IncomingMessageWidget = IncomingMessageWidget(context)
override fun onBindView(view: IncomingMessageWidget, item: IncomingMessageWidget.State) {
view.render(item)
}
}
class OutgoingMessageBinding : ItemBinding<OutgoingMessageWidget.State, OutgoingMessageWidget> {
override fun onCreateView(context: Context): OutgoingMessageWidget = OutgoingMessageWidget(context)
override fun onBindView(view: OutgoingMessageWidget, item: OutgoingMessageWidget.State) {
view.render(item)
}
}
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import kotlin.reflect.KClass
class MultitypeAdapter : ListAdapter<Any, RecyclerView.ViewHolder>(DiffCallback()) {
val bindings = mutableMapOf<KClass<*>, ItemBinding<*, *>>()
inline fun <reified T : Any, reified V : View> register(binding: ItemBinding<T, V>) {
bindings[T::class] = binding
}
inline operator fun <reified T : Any, reified V : View> ItemBinding<T, V>.unaryPlus(){
register(this)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = bindings.values.elementAt(viewType).onCreateView(parent.context)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item: Any = getItem(position)
val viewDelegate = bindings.values.elementAt(holder.itemViewType) as ItemBinding<Any, View>
viewDelegate.onBindView(holder.itemView, item)
}
override fun getItemViewType(position: Int): Int = bindings.keys.indexOf(getItem(position)::class)
private class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
interface ItemBinding<T : Any, V : View> {
fun onCreateView(context: Context): V
fun onBindView(view: V, item: T)
}
fun RecyclerView.withBindings(registerTypes: MultitypeAdapter.() -> Unit) {
adapter = MultitypeAdapter().apply(registerTypes)
}
fun RecyclerView.submitList(list: List<Any>) {
(adapter as MultitypeAdapter).submitList(list)
}
private class DiffCallback : DiffUtil.ItemCallback<Any>() {
override fun areItemsTheSame(oldItem: Any, newItem: Any): Boolean = oldItem == newItem
override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean = oldItem == newItem
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment