-
Notifications
You must be signed in to change notification settings - Fork 726
Saving View State
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 Carousel scroll position.
Saved state should not overlap with any props applied by the EpoxyModel. For example, a CarouselModel can set what items to show in the carousel, and the saved view state would restore scroll position for those items.
It does not work well to save the view state of an EditText, since EditText automatically saves the text value - this prevents you from setting the text from your model because the saved state will override it.
To prevent saved view state from conflicting with model props like that, make sure that they are completely independent!
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.
State is only restored on a view's initial bind. If the model is updated while the view is still on screen then the model will be rebound to the view (in order to apply the changes), but the saved view state will not be applied again.
To save the state across separate adapter instances you must call onSaveInstanceState
on your Epoxy controller (eg in your activity's onSaveInstanceState
method), and then restore it with onRestoreInstanceState
once the controller is created again. This will preserve the view state when the activity or fragment is recreated.
Use the saveViewState
param in the ModelView annotation
@ModelView(saveViewState = true)
Override EpoxyModel#shouldSaveViewState
and return true.
Models generated from databinding layouts cannot currently support saved state. Open an issue if you need support for this.
If you have a view inside of an EpoxyModelGroup that you would like to save, then the corresponding nested model must have saved state enabled for it.
Additionally, if your xml is set up using view stubs 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.
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.