This article will help you understand the structure of Flutter lists and slides. From the common ListView to the internal implementation of NestedScrollView, this article will help you better understand and use Flutter lists.

This is not a tutorial on how to use the API, but something that you don’t usually touch on in your daily development, but is important.

Flutter slip list

The common sliding-list scenario in Flutter simply consists of three parts:

  • Viewport: it’s a MultiChildRenderObjectWidget controls,“What it provides is a window, the size of the viewable area where the list is located;”
  • Scrollable :“It swipes through gestures.”, such as VerticalDragGestureRecognizer and HorizontalDragGestureRecognizer;
  • SliverRenderSliver, to be exact,“It’s primarily used to lay out and render content in a Viewport;”

Take ListView for example, as shown in the figure above is the change of ListView sliding process, where:

  • greenViewportThat’s the size of the list window that we saw;
  • The purple is for gesturesScrollableLet the yellow partSliverList 在 ViewportTo produce sliding;
  • The yellow part isSliverListThat’s what happens when we slideViewportThe position of the inside has changed;

With this basic idea in mind, Viewport and Scrollable implementations are generally common, so “different slivers can be implemented in a Flutter by customizing and combining different slivers to complete the layout”.

“Exactly, the performLayout of RenderSliver is completed, and the Corresponding SliverGeometry is obtained through SliverConstraints.”

So in Flutter:

  • ListViewUsing theSliverFixedExtentListorSliverList;
  • GridViewUsing theSliverGrid;
  • PageViewUsing theSliverFillViewport;

Of course, there is a special SingleChildScrollView, because it is a slider for a single child. Instead of using RenderSliver, it directly defines a RenderObject (RenderBox). And ** “Slide child offset directly on performLayout” **.

RenderSliver

We all know that the overall rendering process in Flutter is Widget -> Element -> RenderObejct -> Layer, and that “the layout and rendering logic in Flutter is RenderObejct”.

RenderObejct can actually be divided into two basic subclasses:

  • RenderBoxRenderBox: We ** use RenderBox for layout controls **;
  • RenderSliver :“Mainly used in Viewport for layout.”The immediate children in Viewport also need to be RenderSliver;

So at this point you might have a question: RenderSliver is not used in SingleChildScrollView. RenderBox can also be used to slide a list.

RenderBox

RenderBox is used inside SingleChildScrollView, so naturally the entire child will be arranged and calculated during the layout process, and offset and clip are used to complete the movement effect during drawing. Such an implementation “suffers when the child is complex or too long”.

RenderSliver

RenderSliver is more complex than RenderBox. RenderSliver is designed to obtain a SliverGeometry through SliverConstraints.

  • In SliverConstraints there is remainingPaintExtent which can be used to indicate the specific size of the remaining drawable;

  • SliverGeometry also has parameters such as scrollExtent (the sliding distance), paintExtent (the drawing size), layoutExtent (the size range of the layout), visible(whether to draw), and so on.

So by using this part of the parameter, “the Viewport can achieve dynamic management, saving resources, according to the SliverGeometry to determine how much content needs to be drawn, how much content is left to draw, what layout needs to load, and so on.”

“Simply put, you can ‘lazily load’ and draw on demand, resulting in a smoother sliding experience.”

Take the ListView for example, as shown in the figure above is a ListView with a height of 701. After the actual layout is rendered, the SliverGeometry output of the SliverList will be:

  • Set the height of each item to 114;
  • scrollExtentIt’s 2353, so the whole sliding distance is equal to 2353;
  • paintExtentIt’s 701 becauseListView 的 ViewportIt’s 701, so fromSliverConstraintsTo get theremainingPaintExtentIs 701.“So by default you only need to draw and lay out the section at height 701;”(Because the default paintExtent = layoutExtent)
  • The extra blue 8-9 parts of item are due to theSliverConstraintsThere will be one calledremainingCacheExtent, which represents the area of the layout that needs to be cached ahead of time. This is the “pre-layout” area, which has a default size ofDefaultCacheExtent = 250.0;

The ListView height is 701, and the defaultCacheExtent extent is 250 by default. If the ListView height is 114, then the ListView height is 8.3. Take integers, that is, 9 items, and you get 114 * 9 = 1026. Inside the SliverList is the endScrollOffset parameter.

So, “The ListView will output a SliverGeometry with a paintExtent of 701 and a cacheExtent of 1026.”

As you can see from this example, “RenderSliver is much better and more flexible in terms of the overhead and logic of implementing slidable lists than RenderBox”, which is why RenderSliver is used in Viewport instead of RenderBox.

⚠️ Note that it is easy to make a mistake here: The ListView consists of Viewport + Scrollable and a RenderSliver, so there is only one RenderSliver in the ListView, not multiple renderslivers. To use multiple RenderSlivers, you need to use a CustomScrollView.

Finally, the CustomScrollView is actually a “slider that opens the RenderSliver array to be configurable”, for example:

  • Through the use ofSliverList + SliverGridYou can put together a variety of sliding lists;
  • throughCupertinoSliverRefreshControl +  SliverListImplement a similar iOS native drop-down refresh list;

Other built-in Slivers available include: SliverPadding, SliverFillRemaining, SliverFillViewport, SliverPersistentHeader, SliverAppbar, and more.

NestedScrollView

Why is NestedScrollView singled out? This is because NestedScrollView is not the same as the sliding list implementation described earlier.

An internal

As shown in the figure above, NestedScrollView inherits CustomScrollView and then defines a custom NestedScrollViewViewport to achieve the linkage effect.

So what’s so special about that? As shown in the following code, this is a common mode for using NestedScrollView. Do you see anything special about it?

The body of the NestedScrollView is nested with a ListView. The ListView itself is a Viewport + Scrollable + SliverList. And NestedScrollView itself also has a NestedScrollViewViewport.

“So the implementation of NestedScrollView is essentially a Viewport nested within a Viewport, with two scrollables.” And the nested ListView is placed inside the Sliver of NestedScrollView, as shown below.

There are several key objects in this, among them:

  • SliverFillRemaining: Fill up the remaining space of the Viewport. In NestedScrollView, fill up the remaining space beyond the header.

  • NestedScrollViewViewport: On the basis of the original Viewport, added a SliverOverlapAbsorberHandle parameters is a ChangeNotifier SliverOverlapAbsorberHandle itself, It is mainly used to send notifications when markNeedsLayout, such as the header part;

So NestedScrollView is essentially nested between two viewports, so how do you handle the sliding relationship between them? “That brings us to the _NestedScrollCoordinator object in NestedScrollView.”

_NestedScrollCoordinator

The _NestedScrollCoordinator implementation is complicated. A _NestedScrollCoordinator creates two _nestedScrollControllers:

  • _outerController: belong to_NestedScrollViewCustomScrollViewIts controller, which is its own controller;
  • _innerController: belong tobodyThe controller;

Within the ListView superclass ScrollView, is used by default PrimaryScrollController. Of this controller (context), Because PrimaryScrollController is an InheritedWidget.

The whole linkage sliding process is mainly related to the two _NestedScrollControllers created by _NestedScrollCoordinator:

  • The main function of _NestedScrollController is to replace ScrollPosition with _NestedScrollPosition;

  • The _NestedScrollCoordinator combines the _outer and _inner two _nestedScrollControllers (_outer and _inner are applied to the NestedScrollView and _inner, respectively) body);

  • _NestedScrollPosition Transfers gesture operations such as Drag back to the _NestedScrollCoordinator.

  • Finally, the drag and applyUserOffset methods of _NestedScrollCoordinator are used to assign inside and outside scrolling.

SliverPersistentHeader

The SliverPersistentHeader is the SliverAppBar that is commonly used in NestedScrollView. Essentially, “SliverAppBar is built on SliverPersistentHeader.”

SliverPersistentHeader has two properties, floating and pinned, the main difference is that the RenderSliver implementation is used, And ** “The final difference is actually the different output SliverGeometry” **.

In the first _SliverFloatingPinnedPersistentHeader and finally a comparison between _SliverScrollingPersistentHeader for example, as shown in the following code, On the floating and pinned Sliver, you can see that both paintExtent and layoutExtent have a minimum value.

“So,SliverThe principle of being immobilized, in fact, is thatViewportI got itpaintExtent 和 layoutExtentIt’s not zero, so it’s going to continue to be thisSliverDraw the content of the corresponding area.”

Finally, note that “when you use SliverPersistentHeader to anchor the head, the body list does not know that there is a fixed area at the top.” So if you don’t do any extra processing at this point, then for the body, the paintOrigin starts at the top rather than below the fixed area.

As you can see in the GIF above, item0 doesn’t stop sliding in the orange area, but keeps sliding up because the body list doesn’t know there’s a fixed area at the top.

This can be solved by using the combination of SliverOverlapAbsorber + SliverOverlapInjector:

  • Embedded in the outer layer of the SliverPersistentHeader is a SliverOverlapAbsorber for absorbing the height of the SliverPersistentHeader;

  • The SliverOverlapInjector configured this height into the body list to let the list know that there was a fixed-height region at the top;

Android Advanced Development System Advanced notes, the latest interview review notes PDF,My lot

At the end of the article

Your likes collection is the biggest encouragement to me! Welcome to follow me, share Android dry goods, exchange Android technology. If you have any comments or technical questions about this article, please leave a comment in the comments section.