Implementing RecyclerView Adapters with BaseRecyclerViewAdapterHelper

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()

Tags: Android RecyclerView adapter BaseRecyclerViewAdapterHelper kotlin

Posted on Fri, 15 May 2026 20:23:23 +0000 by wyred