Skip to content

Instantly share code, notes, and snippets.

@MRezaNasirloo
Created September 2, 2021 10:30
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 MRezaNasirloo/2bb102e0abdef60a483ea0a7db3041c4 to your computer and use it in GitHub Desktop.
Save MRezaNasirloo/2bb102e0abdef60a483ea0a7db3041c4 to your computer and use it in GitHub Desktop.
This Adapter eliminates the need to write custom RecyclerView.Adapters
package com.mrezanasirloo.adapter
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
/**
* This adapter eliminates the need to write custom [RecyclerView.Adapter]s and
* [RecyclerView.ViewHolder]s by delegating the view holder creation and binding to the [Item] class
*/
class GeneralAdapter(
private val items: List<Item>
) : RecyclerView.Adapter<ViewHolder>() {
private var lastViewTypeLookup: Item? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(itemViewType(viewType).onCreateView(parent))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
items[position].onBind(holder, position)
}
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
holder.item?.unbind(holder)
}
override fun getItemViewType(position: Int): Int {
/** Finds and holds a reference to the last view type requested to
* eliminate viewType lookup time
*/
lastViewTypeLookup = items.takeIf { position >= 0 && position < items.size }?.get(position)
checkNotNull(lastViewTypeLookup) { "Invalid position $position" }
return lastViewTypeLookup!!.viewType
}
/**
* Returns the last viewType lookup otherwise finds it.
* The last [lastViewTypeLookup] cannot be null it this point
* The find mechanism is just a safeguard against future internal change of [RecyclerView.Adapter]
*/
private fun itemViewType(viewType: Int): Item {
return lastViewTypeLookup?.takeIf { it.viewType == viewType }
?: items.find { it.viewType == viewType }
?: throw IllegalStateException("Could not find item for viewType: $viewType")
}
override fun getItemCount(): Int = items.size
}
package com.mrezanasirloo.adapter
import android.view.View
/**
* Extend this class to show different type of Items inside a [GeneralAdapter]
*/
abstract class Item {
open val viewType: Int = javaClass.hashCode()
abstract fun onCreateView(parent: View): View
open fun onBind(holder: ViewHolder, position: Int) {}
open fun onUnbind(holder: ViewHolder) {}
internal fun bind(holder: ViewHolder, position: Int) {
holder.bind(this)
onBind(holder, position)
}
internal fun unbind(holder: ViewHolder) {
holder.unbind()
onUnbind(holder)
}
}
package com.mrezanasirloo.adapter
import android.view.View
import androidx.recyclerview.widget.RecyclerView
/**
* Holds a reference to an [Item] until its [unbind]
*/
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
internal var item: Item? = null
private set
internal fun bind(item: Item) {
this.item = item
}
internal fun unbind() {
item = null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment