Skip to content

Cyclic Adapters

Eli Hart edited this page Feb 25, 2018 · 3 revisions

Cyclic adapters allow items in a RecyclerView to be scrolled through indefinitely, repeating the same set of items over and over again.

For example, if you have 10 items in your Adapter, making it cyclic would cause those ten items to be shown back to back, over and over again as the user scrolls infinitely to the left or right.

This behavior is not explicitly supported in RecyclerView, but there are some tricks we can use to fake it.

A Wrapped Adapter

One option is to wrap your Adapter in a cyclic adapter. Such an adapter is provided at https://gist.github.com/elihart/f404cdc8fac0241ce8e15b53de85d66f

This adapter reports a item count of, Integer.MAX_VALUE, but all items are accessed via position % wrappedAdapter.getItemCount() to get a valid index into the actual data set.

This allows the RecyclerView to easily show the same set of items on repeat.

To use with Epoxy, copy the adapter into your project, and wrap your adapter like so:

EpoxyController controller = new MyController();
Adapter cyclicAdapter = new CyclicAdapter(controller.getAdapter());
recyclerView.setAdapter(cyclicAdapter);

One issue with this approach is that any adapter changes will only trigger view updates in the initial set of items. It is not recommended to use this if you have to update adapter content.

If that is needed, it could potentially be supported by modifying the observerDelegate to also notify the changes at all cyclic intervals. A downside to this is it would trigger a very large number of changes since the adapter reports an item count of Integer.MAX_VALUE. A compromise could be to make the item count 20 times larger than the original - this should be enough to provide the illusion of infinite cyclicalness, without providing too many adapter notifications on item change.

Because of this limitation this adapter is not officially part of the Epoxy library, but you're welcome to copy the code into the project and modify it as needed.

If you would like to improve on this Cyclic Adapter and add it to Epoxy, please open a PR :)

Manually Duplicating Models

Another option to produce cyclic behavior is to manually duplicate models in your buildModels method.

This could look like this

protected void buildModels() {
  for (int i = 0; i < 10; i++) {
    actualBuildModelsCode();
  }
}

This would duplicate the same models 10 times. 10 is an arbitrary number here - it should ideally be high enough so that nobody will realistically scroll through the duplicated content that many times.

The benefit of this approach over the Cyclic Adapter is that item changes will correctly be reflected in the cylic pages.

The downside to this approach is extra resource usage to created models. That is why 10 is used instead of a higher number. It is a balance between creating enough buffer room to give the appearance of infinite scrolling, without creating unnecessarily many models.

Starting in the middle of the adapter

Both of these approaches result in a RecyclerView that starts at position 0, and can scroll cyclically to the right. If you want to allow scrolling both left and right from the outset, then you can manually scroll the RecyclerView to the middle of its item count immediately after the adapter is set.