Skip to content

Instantly share code, notes, and snippets.

@JavierSegoviaCordoba
Last active August 6, 2020 10:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JavierSegoviaCordoba/3b01eb78e91d67b625966c1700927ac4 to your computer and use it in GitHub Desktop.
Save JavierSegoviaCordoba/3b01eb78e91d67b625966c1700927ac4 to your computer and use it in GitHub Desktop.
/**
* Usage:
* private val adapter by listAdapter(UserItemBinding::inflate, User::userId) { user: User ->
* textViewName.text = user.username
* imageView.load(user.avatarUrl)
* }
* @param [binding] is the item binding generated via ViewBinding or DataBinding
* @param [property] is the item property used by DiffUtil, if it is not indicated or it is null, DiffUtil will search
* for a property called id
* @param [onBind] is the lambda which include the item object
*/
class BaseListAdapter<ITEM : Any, VB : ViewBinding>(
private val binding: (LayoutInflater, ViewGroup, Boolean) -> VB,
property: KProperty1<ITEM, *>? = null,
private val onBind: (VB.(ITEM) -> Unit)
) : ListAdapter<ITEM, BaseListAdapter<ITEM, VB>.BaseViewHolder>(
BaseDiff<ITEM>(property)
) {
private var onClick: ((ITEM, position: Int) -> Unit)? = null
fun onClick(listener: (ITEM, position: Int) -> Unit) {
onClick = { item, position -> listener(item, position) }
}
private var onLongClick: ((ITEM, position: Int) -> Unit)? = null
fun onLongClick(listener: (ITEM, position: Int) -> Unit) {
onLongClick = { item, position -> listener(item, position) }
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return BaseViewHolder(binding.invoke(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(viewHolder: BaseViewHolder, position: Int) {
return viewHolder.bind(getItem(position))
}
inner class BaseViewHolder(val binding: VB) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: ITEM) {
with(binding) {
root.setOnClickListener { onClick?.invoke(item, adapterPosition) }
root.setOnLongClickListener {
onLongClick?.invoke(item, adapterPosition).run { true }
}
onBind.invoke(binding, item)
}
}
}
}
open class BaseDiff<T : Any>(private val property: KProperty1<T, *>?) : DiffUtil.ItemCallback<T>() {
override fun areItemsTheSame(old: T, new: T): Boolean {
val oldProperty = old::class.members.firstOrNull { it == property }
val newProperty = new::class.members.firstOrNull { it == property }
return if (oldProperty != null && newProperty != null) oldProperty == newProperty else false
}
@SuppressLint("DiffUtilEquals")
override fun areContentsTheSame(old: T, new: T): Boolean = old == new
}
inline fun <reified ITEM : Any, VB : ViewBinding> listAdapter(
noinline binding: (LayoutInflater, ViewGroup, Boolean) -> VB,
identifier: KProperty1<ITEM, *>? = null,
noinline onBind: VB.(ITEM) -> Unit
): Lazy<BaseListAdapter<ITEM, VB>> {
return lazy { BaseListAdapter(binding, identifier, onBind) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment