introduce

Listview in the construction of the principle of the analysis recorded some notes, I hope to help you. Listview as a whole has a large structure, so it will consist of several chapters. To read the following, you need to have an understanding of how to build, layout, and draw flutter widgetsCopy the code

series

ListView source code analysis of child-view construction

In this article we will analyze the Viewport used to display children in the ListView (focusing on displaying children).

review

Let’s review the flow chart from the previous part

Visible in the ListView is the statelessWidget, which builds the sliverList in the build() method to create children, then wraps it with Scrollable alignment, and creates a Viewport.

Scrollable will be in the next post, so let’s look at viewPort first.

Viewport

From the notes, we know:

The viewport is the backbone of the scrolling mechanism, displaying children according to its size and given ‘offset’. When offset changes (e.g., scrolling), different children pass through the window.

The viewport on top of the sliver is defined by the size and offset of the viewport. And we’re going to change that offset as we scroll.

In other words, we have a window above the sliver, we look through the window to see the sliver, and when we scroll, we change the window position.

suspended

So let’s pause here

Renderobjectwidget is a direct descendant of the renderObjectwidget viewport. In order to avoid confusing things, here is a brief description of how widgets, Elements, and RenderObjects can be constructed and rendered:

When rendering begins, element is created through createElement(). Element then creates the widget by calling the widget’s build method in its performRebuild() method. Widgets inherit from xxRenderObjectWidget(of course, the highest level is widgets). In the performRebuild() method, createRenderObject () of the widget is called to create the corresponding renderObject and attachXXX() method is called to attach it to the renderObject tree. The paint () method of the renderObject is called to complete the drawing.

This is the general process, interested in the article can find detailed understanding, we continue.

Continue to

Look at the picture above you can see it inherited from MultiChildRenderObjectWidget, overwrite its three methods

Because of the three methods are written, so we do not need to check MultiChildRenderObjectWidget source As long as you know, our slivers (children) are MultiChildRenderObjectWidget preservedCopy the code

Element (_ViewportElement)

@override _ViewportElement createElement() => _ViewportElement(this); // The following two methods are to create the render object and update it. // The two methods are similar in nature. We analyze @override RenderViewport createRenderObject(BuildContext Context) @override void updateRenderObject(BuildContext context, RenderViewport renderObject)Copy the code

_ViewportElement & MultiChildRenderObjectElement

Because the _ViewportElement of method and let’s be something not too big relations, we see MultiChildRenderObjectElement directly.

class MultiChildRenderObjectElement extends RenderObjectElement
Copy the code

Instead of ‘add, delete, change, check’, let’s focus on these two things

BuildOwner <Element> children; buildOwner <Element> children; buildOwner <Element> children; buildOwner <Element> children // Layout and paint begin after this methodCopy the code

We know that the Build () method is called in the performRebuild() method to create a widget.

Once a widget is created, it creates its element using the inflateWidget(), and then calls Element’s mount () method to mount it to the Element tree.

Of course, the actual process is not that simple, and inflateWidget() is not the only method called by performRebuild(). Update is also called.Copy the code
@override void mount(Element parent, Dynamic newSlot) {/ / here called the mount of the parent () method will eventually call / / MultiChildRenderObjectWidget (where is continue above) / / createRenderObject / / to create () method Super.mount (parent, newSlot); super.mount(parent, newSlot); _children = List<Element>(widget.children.length); Element previousChild; for (int i = 0; i < _children.length; i += 1) { final Element newChild = inflateWidget(widget.children[i], IndexedSlot<Element>(i, previousChild)); _children[i] = newChild; previousChild = newChild; }}Copy the code

In the code, after the Viewport element is created, its mount method is called, and inside the method, we generate elements _children based on children (the slivers we passed).

So, where is this List _children used? We see another method above:

  @override
  void visitChildren(ElementVisitor visitor) {
    for (final Element child in _children) {
      if (!_forgottenChildren.contains(child))
        visitor(child);
    }
  }
Copy the code

This method traverses the child, so let’s see where this method is called. CTRL + left, this code calls:

  RenderObject get renderObject {
    RenderObject result;
    void visit(Element element) {
      assert(result == null); // this verifies that there's only one child
      if (element is RenderObjectElement)
        result = element.renderObject;
      else
        element.visitChildren(visit);
    }
    visit(this);
    return result;
  }
Copy the code

This is a get method that returns the renderObject currently held by Element, and one of the places it calls is the attachRenderObject () method in the mount method above, after the renderObject has been created.

The attachRenderObject () method is overridden, and the insertChildRenderObject() method is called internally (in this case) to insert the Child's renderObject into the renderObject tree.Copy the code

At this point, the renderObject tree for the entire viewPort and its children is built, and this tree is then used for layout and drawing.

Viewport & Children Layout process

The following figure is the simplification of the above process, which is convenient for us to understand and comb.

Thank you for reading, please point out any mistakes.

Related articles

The structure of PageView has many similarities and even similarities with listView. Maybe the following two chapters can help you understand the principle of flutter scroll view more comprehensively from another perspective

PageView PageController source analysis notes

PageView source and Gesture Arena disambiguation analysis