Skip to content

Saving View State

Eli Hart edited this page Oct 23, 2017 · 9 revisions

RecyclerView does not support saving the view state of its children the way a normal ViewGroup would. Epoxy adds this missing support by managing the saved state of each view on its own.

Saving view state is useful for cases where the view is modified by the user, such as EditText cursor position, or Carousel scroll position. These can be considered transient state that the model doesn't need to know about.

Enabling Saved State

Saving state adds extra overhead when binding models, and is disabled by default. You can enable it on a per model basis for the views that require it.

When this is enabled, Epoxy will manually call View#saveHierarchyState to save the state of the view when it is unbound. That state is restored when the view is bound again. This will save the state of the view as it is scrolled off screen and then scrolled back on screen.

To save the state across separate adapter instances you must call onSaveInstanceState on your Epoxy controller or adapter (eg in your activity's onSaveInstanceState method), and then restore it with onRestoreInstanceState once the adapter is created again. This will preserve the view state when the activity is recreated.

ModelView Models

Use the saveViewState param in the ModelView annotation

@ModelView(saveViewState = true)

Manually Created Models

Override EpoxyModel#shouldSaveViewState and return true.

Databinding Models

Models generated from databinding layouts cannot currently support saved state. Open an issue if you need support for this.

In Model Groups

If you have a view inside of an EpoxyModelGroup that you would like to save, you must set the inflatedId xml attribute on that model's viewstub. For example, in the sample app we have a horizontal recycler nested inside a model group and we want to save the scroll position, so we set an id like so:

<ViewStub
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:inflatedId="@+id/recycler_view" />

Without this the view won't have an id to associate its saved state with.

With multiple RecyclerViews

Saved state does not work properly if you set the same adapter on multiple RecyclerViews. In that case, any model ids that exist in multiple RecyclerViews would cause state for those models to be shared across RecyclerViews.