Unverified Commit ede7c15a authored by xster's avatar xster Committed by GitHub

Add doc describing sliver children's lifecycle and persistence options (#19795)

parent 0f4ea504
......@@ -496,6 +496,63 @@ abstract class BoxScrollView extends ScrollView {
/// )
/// ```
///
/// ## Child elements' lifecycle
///
/// ### Creation
///
/// While laying out the list, visible children's elements, states and render
/// objects will be created lazily based on existing widgets (such as when using
/// the default constructor) or lazily provided ones (such as when using the
/// [ListView.builder] constructor).
///
/// ### Destruction
///
/// When a child is scrolled out of view, the associated element subtree,
/// states and render objects are destroyed. A new child at the same position
/// in the list will be lazily recreated along with new elements, states and
/// render objects when it is scrolled back.
///
/// ### Destruction mitigation
///
/// In order to preserve state as child elements are scrolled in and out of
/// view, the following options are possible:
///
/// * Moving the ownership of non-trivial UI-state-driving business logic
/// out of the list child subtree. For instance, if a list contains posts
/// with their number of upvotes coming from a cached network response, store
/// the list of posts and upvote number in a data model outside the list. Let
/// the list child UI subtree be easily recreate-able from the
/// source-of-truth model object. Use [StatefulWidget]s in the child
/// widget subtree to store instantaneous UI state only.
///
/// * Letting [KeepAlive] be the root widget of the list child widget subtree
/// that needs to be preserved. The [KeepAlive] widget marks the child
/// subtree's top render object child for keep-alive. When the associated top
/// render object is scrolled out of view, the list keeps the child's render
/// object (and by extension, its associated elements and states) in a cache
/// list instead of destroying them. When scrolled back into view, the render
/// object is repainted as-is (if it wasn't marked dirty in the interim).
///
/// This only works if [addAutomaticKeepAlives] and [addRepaintBoundaries]
/// are false since those parameters cause the [ListView] to wrap each child
/// widget subtree with other widgets.
///
/// * Using [AutomaticKeepAlive] widgets (inserted by default when
/// [addAutomaticKeepAlives] is true). Instead of unconditionally caching the
/// child element subtree when scrolling off-screen like [KeepAlive],
/// [AutomaticKeepAlive] can let whether to cache the subtree be determined
/// by descendant logic in the subtree.
///
/// As an example, the [EditableText] widget signals its list child element
/// subtree to stay alive while its text field has input focus. If it doesn't
/// have focus and no other descendants signaled for keep-alive via a
/// [KeepAliveNotification], the list child element subtree will be destroyed
/// when scrolled away.
///
/// [AutomaticKeepAlive] descendants typically signal it to be kept alive
/// by using the [AutomaticKeepAliveClientMixin], then implementing the
/// [wantKeepAlive] getter and calling [updateKeepAlive].
///
/// ## Transitioning to [CustomScrollView]
///
/// A [ListView] is basically a [CustomScrollView] with a single [SliverList] in
......
......@@ -27,6 +27,67 @@ export 'package:flutter/rendering.dart' show
/// of the existing subclasses that provide adaptors to builder callbacks or
/// explicit child lists.
///
/// {@template flutter.widgets.sliverChildDelegate.lifecycle}
/// ## Child elements' lifecycle
///
/// ### Creation
///
/// While laying out the list, visible children's elements, states and render
/// objects will be created lazily based on existing widgets (such as in the
/// case of [SliverChildListDelegate]) or lazily provided ones (such as in the
/// case of [SliverChildListDelegate]).
///
/// ### Destruction
///
/// When a child is scrolled out of view, the associated element subtree, states
/// and render objects are destroyed. A new child at the same position in the
/// sliver will be lazily recreated along with new elements, states and render
/// objects when it is scrolled back.
///
/// ### Destruction mitigation
///
/// In order to preserve state as child elements are scrolled in and out of
/// view, the following options are possible:
///
/// * Moving the ownership of non-trivial UI-state-driving business logic
/// out of the sliver child subtree. For instance, if a list contains posts
/// with their number of upvotes coming from a cached network response, store
/// the list of posts and upvote number in a data model outside the list. Let
/// the sliver child UI subtree be easily recreate-able from the
/// source-of-truth model object. Use [StatefulWidget]s in the child widget
/// subtree to store instantaneous UI state only.
///
/// * Letting [KeepAlive] be the root widget of the sliver child widget subtree
/// that needs to be preserved. The [KeepAlive] widget marks the child
/// subtree's top render object child for keep-alive. When the associated top
/// render object is scrolled out of view, the sliver keeps the child's
/// render object (and by extension, its associated elements and states) in a
/// cache list instead of destroying them. When scrolled back into view, the
/// render object is repainted as-is (if it wasn't marked dirty in the
/// interim).
///
/// This only works if the [SliverChildDelegate] subclasses don't wrap the
/// child widget subtree with other widgets such as [AutomaticKeepAlive] and
/// [RepaintBoundary] via `addAutomaticKeepAlives` and
/// `addRepaintBoundaries`.
///
/// * Using [AutomaticKeepAlive] widgets (inserted by default in
/// [SliverChildListDelegate] or [SliverChildListDelegate]). Instead of
/// unconditionally caching the child element subtree when scrolling
/// off-screen like [KeepAlive], [AutomaticKeepAlive] can let whether to
/// cache the subtree be determined by descendant logic in the subtree.
///
/// As an example, the [EditableText] widget signals its sliver child element
/// subtree to stay alive while its text field has input focus. If it doesn't
/// have focus and no other descendants signaled for keep-alive via a
/// [KeepAliveNotification], the sliver child element subtree will be
/// destroyed when scrolled away.
///
/// [AutomaticKeepAlive] descendants typically signal it to be kept alive by
/// using the [AutomaticKeepAliveClientMixin], then implementing the
/// [wantKeepAlive] getter and calling [updateKeepAlive].
/// {@endtemplate}
///
/// See also:
///
/// * [SliverChildBuilderDelegate], which is a delegate that uses a builder
......@@ -383,6 +444,8 @@ abstract class SliverMultiBoxAdaptorWidget extends RenderObjectWidget {
/// [SliverFixedExtentList] does not need to perform layout on its children to
/// obtain their extent in the main axis and is therefore more efficient.
///
/// {@macro flutter.widgets.sliverChildDelegate.lifecycle}
///
/// See also:
///
/// * [SliverFixedExtentList], which is more efficient for children with
......@@ -437,6 +500,8 @@ class SliverList extends SliverMultiBoxAdaptorWidget {
/// )
/// ```
///
/// {@macro flutter.widgets.sliverChildDelegate.lifecycle}
///
/// See also:
///
/// * [SliverPrototypeExtentList], which is similar to [SliverFixedExtentList]
......@@ -505,6 +570,8 @@ class SliverFixedExtentList extends SliverMultiBoxAdaptorWidget {
/// )
/// ```
///
/// {@macro flutter.widgets.sliverChildDelegate.lifecycle}
///
/// See also:
///
/// * [SliverList], which places its children in a linear array.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment