Skip to content

⚒ Modular components for RecyclerView development enforcing clean, reusable and testable code, with built-in support for paging and complex hierarchies of data.


Notifications You must be signed in to change notification settings


Repository files navigation

Build Status Release Issues

Need support, consulting, or have any other business-related question? Feel free to get in touch.

Like the project, make profit from it, or simply want to thank back? Please consider sponsoring me!


A collection of modular elements for RecyclerView lists, alternative to Google's Paging library, designed in Kotlin with these goals in mind:


Design features:

  • Separation of concerns: we split the model component into Sources, and the UI component into Presenters. [docs]
  • Simplicity: No need to extend Adapters, ViewHolders or all that Paging lib. boilerplate.
  • Reusability: as a result, each Source and Presenter is an independent piece of code that can be reused.
  • Modularity: let the adapter accept multiple Sources and Presenters. [docs]
  • Testability: a consequence of the above, each component can be independently tested.
  • Coordination: let Sources declare dependencies among them, in a CoordinatorLayout.Behavior fashion. [docs]
  • Paging: built-in concept of Page. [docs]
  • Integration with Arch components: heavy use of LiveData and Lifecycles, extensions for data binding.
  • Animations: give Presenterss fine grained control over how to animate each item [docs]

If you are curious about how it works in practice, take a look at the sample app in the app module.


If you like the project, make profit from it, or simply want to thank back, please consider sponsoring me through the GitHub Sponsors program! You can have your company logo here, get private support hours or simply help me push this forward.

Feel free to contact me for support, consulting or any other business-related question.


Please read the official website for setup instructions and documentation. You might also be interested in our changelog. After migrating
to Elements, your code will look like the examples below.

Simplest single-paged list:

val data = listOf("Monday", "Tuesday", "Wednesday", "Friday", "Saturday", "Sunday")
    .addPresenter(Presenter.simple(context, R.layout.item, { view, day -> view.text = day }))

Paged list with multiple sources and presenters, headers, ads, error/empty indicators and progress bars:

    .addSource(ContactsSource()) // Add a paged list of contacts
    .addSource(ContactsHeaderSource()) // Add the letters A, B, C as a header
    .addSource(AdSource(5)) // Add some ads each 5 items
    .addPresenter(Presenter.forLoadingIndicator(context, R.layout.loading))
    .addPresenter(Presenter.forErrorIndicator(context, R.layout.error))
    .addPresenter(Presenter.forEmptyIndicator(context, R.layout.empty))