Skip to content

RecyclerView adapter delegate multi type with 2024 up-to-date RecyclerView

License

Notifications You must be signed in to change notification settings

Mercandj/recyclerview-adapter

Repository files navigation

RecyclerView - Adapter Delegate Multi Type

Why & What?

  • Why: On Android, it's not built-in to support multi type on RecyclerView.
  • What: A light weight library to support multi type and decoupling Rows/Cells from the list.

How to integrate?

Step 1. In project root build.gradle or build.gradle.kts, add:

allprojects {
    repositories {
        maven { url 'https://jitpack.io' } // Groovy: build.gradle
        maven(url = "https://jitpack.io") // Kotlin: build.gradle.kts
    }
}

Step 2. Add the dependency in app build.gradle or build.gradle.kts:

dependencies {
    implementation("com.github.Mercandj:recyclerview-adapter:1.00.03")
}

Step 3. Prepare multi types

class CatRowViewAdapterDelegate :
    AbsListItemAdapterDelegate<Any, Any, CatRowViewAdapterDelegate.ViewHolder>() {

    override fun isForViewType(item: Any, items: List<Any>, position: Int) =
        item is CatRowViewModel

    override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
        val view = CatRowView(parent.context)
        view.layoutParams = RecyclerView.LayoutParams(
            RecyclerView.LayoutParams.MATCH_PARENT,
            RecyclerView.LayoutParams.WRAP_CONTENT
        )
        return ViewHolder(view)
    }

    override fun onBindViewHolder(item: Any, viewHolder: ViewHolder, payloads: List<Any>) {
        viewHolder.view.setViewModel(item as CatRowViewModel)
    }

    class ViewHolder(val view: CatRowView) : RecyclerView.ViewHolder(view)
}
data class CatRowViewModel(val name: String)

class CatRowView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    init {
        View.inflate(context, R.layout.cat_row_view, this)
    }

    fun setViewModel(viewModel: CatRowViewModel) {
        findViewById<TextView>(R.id.cat_row_view_name).text = viewModel.name
    }
}

Step 4. Create your multi-type adapter

class AnimalsActivityAdapter : ListDelegationAdapter<List<Any>>() {

    init {
        delegatesManager.addDelegate(CatRowViewAdapterDelegate())
            .addDelegate(DogRowViewAdapterDelegate()) // Do the same as the Cat but for dogs
    }

    fun setViewModels(viewModels: List<Any>) {
        if (items == viewModels) {
            return
        }
        items = viewModels
        notifyDataSetChanged()
    }
}

and affect it to the recycler view

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.animals_activity)
    val recyclerView: RecyclerView = findViewById(R.id.animals_activity_recycler_view)
    recyclerView.layoutManager = LinearLayoutManager(this)
    recyclerView.adapter = adapter
    adapter.setViewModels(
        viewModels = listOf(
            CatRowViewModel("Pimousse"),
            CatRowViewModel("Matcha"),
            DogRowViewModel("Nelson") // Do the same as the Cat but for dogs
        )
    )
}

Sources

  • Copied and adapted from this commit:
  • Why a new library instead of a PullRequest to "com.hannesdorfmann:adapterdelegates4"?
    • The initial goal was to have up-to-date RecyclerView dependency to be able to set the stateRestorationPolicy
    • Why? CF this great article Restore RecyclerView scroll position: link
  • What have been changed from "com.hannesdorfmann:adapterdelegates4"
    • Bump recyclerView
    • Move from Java to Kotlin
    • Remove fancy kotlin DSL support
    • Change the build system from groovy to kotlin
    • Simplify the sample