Adapter Types and Their Implementation
BaseQuickAdapter: Standard Single-Item Adapter
This adapter handles standard lists with click events, data operations, animatiosn, and empty views.
class SimpleListAdapter : BaseQuickAdapter<DataItem, SimpleListAdapter.ItemHolder>() {
class ItemHolder(val binding: ItemDataBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): ItemHolder {
val binding = ItemDataBinding.inflate(LayoutInflater.from(context), parent, false)
return ItemHolder(binding)
}
override fun onBindViewHolder(holder: ItemHolder, position: Int, item: DataItem?) {
holder.binding.itemText.text = item?.content
}
}
For simpler cases without ViewBinding, use QuickViewHolder:
class BasicAdapter : BaseQuickAdapter<DataModel, QuickViewHolder>() {
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): QuickViewHolder {
return QuickViewHolder(R.layout.list_item_layout, parent)
}
override fun onBindViewHolder(holder: QuickViewHolder, position: Int, item: DataModel?) {
holder.getView<TextView>(R.id.text_view).text = item?.title
}
}
BaseMultiItemAdapter: Multiple Layout Types
This adapter supports lists with different item layouts.
class MultiLayoutAdapter(data: List<ContentEntity>) : BaseMultiItemAdapter<ContentEntity>(data) {
class ContentVH(val binding: ContentItemBinding) : RecyclerView.ViewHolder(binding.root)
class HeaderVH(val binding: HeaderBinding) : RecyclerView.ViewHolder(binding.root)
init {
addItemType(CONTENT_TYPE, object : OnMultiItemAdapterListener<ContentEntity, ContentVH> {
override fun onCreate(context: Context, parent: ViewGroup, viewType: Int): ContentVH {
val binding = ContentItemBinding.inflate(LayoutInflater.from(context), parent, false)
return ContentVH(binding)
}
override fun onBind(holder: ContentVH, position: Int, item: ContentEntity?) {
// Bind content data
}
}).addItemType(HEADER_TYPE, object : OnMultiItemAdapterListener<ContentEntity, HeaderVH> {
override fun onCreate(context: Context, parent: ViewGroup, viewType: Int): HeaderVH {
val binding = HeaderBinding.inflate(LayoutInflater.from(context), parent, false)
return HeaderVH(binding)
}
override fun onBind(holder: HeaderVH, position: Int, item: ContentEntity?) {
// Bind header data
}
}).onItemViewType { position, list ->
if (list[position].isHeader) HEADER_TYPE else CONTENT_TYPE
}
}
companion object {
private const val CONTENT_TYPE = 0
private const val HEADER_TYPE = 1
}
}
BaseDifferAdapter: Efficient Data Updates
This adapter uses DiffUtil for efficient partial updates, suitable for large or frequent updated lists.
Data classes must properly implement equality checks. In Kotlin, use data class:
data class UpdateItem(val id: Long, val value: String)
Implement DiffUtil.ItemCallback:
class ItemDiffCallback : DiffUtil.ItemCallback<UpdateItem>() {
override fun areItemsTheSame(oldItem: UpdateItem, newItem: UpdateItem): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: UpdateItem, newItem: UpdateItem): Boolean {
return oldItem == newItem
}
}
Create the adapter:
class DiffAdapter : BaseDifferAdapter<UpdateItem, QuickViewHolder>(ItemDiffCallback()) {
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): QuickViewHolder {
return QuickViewHolder(R.layout.update_item, parent)
}
override fun onBindViewHolder(holder: QuickViewHolder, position: Int, item: UpdateItem?) {
holder.getView<TextView>(R.id.item_label).text = item?.value
}
}
BaseSingleItemAdapter: Single Item Adapter
Used for headers, footers, or other single-item scenarios.
class FooterAdapter : BaseSingleItemAdapter<FooterData, FooterAdapter.FooterHolder>() {
class FooterHolder(view: View) : RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): FooterHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.footer_layout, parent, false)
return FooterHolder(view)
}
override fun onBindViewHolder(holder: FooterHolder, item: FooterData?) {
// Bind footer data
}
}
// Usage
adapter.item = footerData
adapter.setItem(footerData, payload)
QuickAdapterHelper: Composite Adapter Management
This utility combines multiple adapters using ConcatAdapter to add headers, footers, and load states.
val helper = QuickAdapterHelper.Builder(mainAdapter)
.setTrailingLoadStateAdapter(loadMoreAdapter)
.setLeadingLoadStateAdapter(refreshAdapter)
.setConfig(concatConfig)
.build()
recyclerView.adapter = helper.adapter
Helper methods for adapter management:
// Add adapters before or after the main adapter
helper.addBeforeAdapter(headerAdapter)
helper.addAfterAdapter(footerAdapter)
// Remove specific adapter
helper.removeAdapter(someAdapter)
// Clear all adapters before or after the main adapter
helper.clearBeforeAdapters()
helper.clearAfterAdapters()
Event Handling
Click and Long Press Events
// Item click
adapter.setOnItemClickListener { adapter, view, position ->
// Handle click
}
// Item long press
adapter.setOnItemLongClickListener { adapter, view, position ->
// Handle long press
true
}
// Child view click
adapter.addOnItemChildClickListener(R.id.child_view) { adapter, view, position ->
// Handle child click
}
// Child view long press
adapter.addOnItemChildLongClickListener(R.id.child_view) { adapter, view, position ->
// Handle child long press
true
}
Debounced Click Events
Prevent rapid double-clicks with default 500ms interval:
adapter.setOnDebouncedItemClick { adapter, view, position ->
// Handle debounced click
}
adapter.addOnDebouncedChildClick(R.id.child_view) { adapter, view, position ->
// Handle debounced child click
}
Data Operations
Setting and Modifying Data
// Set complete list
adapter.submitList(dataList)
// Modify item at specific position
adapter[position] = newItem
// Add items
adapter.add(singleItem)
adapter.add(position, singleItem)
adapter.addAll(itemList)
adapter.addAll(position, itemList)
// Remove items
adapter.remove(specificItem)
adapter.removeAt(position)
Item Animations
Built-in Animasions
adapter.setItemAnimation(BaseQuickAdapter.AnimationType.AlphaIn)
adapter.setItemAnimation(BaseQuickAdapter.AnimationType.ScaleIn)
adapter.setItemAnimation(BaseQuickAdapter.AnimationType.SlideInBottom)
adapter.setItemAnimation(BaseQuickAdapter.AnimationType.SlideInLeft)
adapter.setItemAnimation(BaseQuickAdapter.AnimationType.SlideInRight)
Custom Animations
Create custom animations by extending ItemAnimator:
class CustomItemAnimation : ItemAnimator {
override fun animator(view: View): Animator {
val fadeAnim = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f)
val scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1.5f, 1f)
val scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1.5f, 1f)
scaleYAnim.interpolator = OvershootInterpolator()
scaleXAnim.interpolator = OvershootInterpolator()
val animSet = AnimatorSet()
animSet.duration = 400
animSet.play(fadeAnim).with(scaleXAnim).with(scaleYAnim)
return animSet
}
}
// Apply custom animation
adapter.itemAnimation = CustomItemAnimation()