Introduction of the Widget

The Widget Describes the configuration for an [Element], the structure of the Flutter. And is an immutable description that will be associated with Element later.

The contents of the widget-Element-RenderObject trees will be sorted later

There are three priorities:

  1. A Widget is an immutable configuration information
  2. The Widget will be associatedElementtype
  3. Abstract class that actually inherits subclasses during development:StatefulWidget.StatelessWidget.
  4. StatefulWidgetThe mutable state of is completely dependent on the associatedState
abstract class Widget extends DiagnosticableTree {
  const Widget({ this.key });
  
  final Key key;
    
  @protected
  ElementcreateElement(); ./// Whether the `newWidget` can be used to update an [Element] that currently
  /// has the `oldWidget` as its configuration.
  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    returnoldWidget.runtimeType == newWidget.runtimeType && oldWidget.key == newWidget.key; }}Copy the code

StatelessWidgetLife cycle of

StatelessWidget as a StatelessWidget, the lifecycle is simple:

  1. const StatelessWidget({ Key? key }) : super(key: key);The constructor
  2. StatelessElement createElement() => StatelessElement(this);The Element associated with the Widget,
  3. Widget build(BuildContext context);instructionsThe framework calls this method when this widget is inserted into the tree
//Element will only have widgets inside
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  StatelessElement(StatelessWidget widget) : super(widget);

  /// use
  @override
  StatelessWidget get widget => super.widget as StatelessWidget;

  @override
  Widget build() => widget.build(this); 

  @override
  void update(StatelessWidget newWidget) {
    super.update(newWidget);
    _dirty = true; rebuild(); }}Copy the code

StatefulWidgetLife cycle of

A StatefulWidget is a StatefulWidget with the following lifecycle of the State associated with it:

  1. widget: const StatefulWidget({ Key? key }) : super(key: key);
  2. widget: StatefulElement createElement() => StatefulElement(this);
  3. widget: State createState()
  4. state: constructor
  5. state: initState
  6. state: didChangeDependencies(ifInheritedWidget.rebuild= >child.didChangeDependencies)
  7. state: Widget build(BuildContext context); (setState()= >didUpdateWidget= >build)
  8. The state:Widget - ElementjointreeIn the
  9. state: deactivate
  10. state: dispose
  11. willElementremovetrue
  1. InheritedWidget is called in childNode when the InheritedWidget method is rebuiltdidChangeDependencies
  1. When the setState() method is calleddidUpdateWidgetMethod, and then callbuild

Several key elements in the above process:

  1. inStatefulWidgetIn the callcreateElement()Method, the key content:
// StatefulWidget is called when the Widget is mounted to the tree
StatefulElement createElement() {
    // Element's constructor
    return StatefulElement(this);
}
​
/// Creates an element that uses the given widget as its configuration.
/// Element constructor
/// 1.The widget.creatEstate () method is actively called and created_state!!!
/// 2. Then, hold the Element and widget in State
StatefulElement(StatefulWidget widget): _state = widget.createState(), super(widget) {
    ...
   state._element = this;
   state._widget = widget;
}
Copy the code
  1. In createState(), it may be called multiple times. For example, if the widget is inserted into the tree in multiple locations, the framework will create a separate [State] object for each location

  2. SetState implementation with dirty Element tags and updates:

    /// Methods in State
    void setState(VoidCallback fn) {
       // 先调用 fn() ... 
       final Object? result = fn() as dynamic; _element! .markNeedsBuild(); }/// Methods in Element
    /// Marks the element as dirty and adds it to the global list of widgets to
    /// rebuild in the next frame.
    ///
    /// Since it is inefficient to build an element twice in one frame,
    /// applications and widgets should be structured so as to only mark
    /// widgets dirty during event handlers before the frame begins, not during
    /// the build itself.
    void markNeedsBuild() {
        ...
        _dirty = true; // Just marking Element is added to the global Dirty list, which is updated the next frame through the loopowner! .scheduleBuildFor(this); // Owner is set by the parent. Owner passed in when mount is called
    }
    
    // BuildOwner class -- a management class in the Framework
    /// Adds an element to the dirty elements list so that it will be rebuilt
    /// when [WidgetsBinding.drawFrame] calls [buildScope].
    void scheduleBuildFor(Element element) {
        ...
        _dirtyElements.add(element); // Add element to the global dirty list
        element._inDirtyList = true;
    }
    Copy the code