current position:Home>[flutter topic] 101 what is flutter elements Yyds dry goods inventory

[flutter topic] 101 what is flutter elements Yyds dry goods inventory

2022-04-29 11:10:5051CTO

       A little while ago, I had a brief understanding of Widget Knowledge about , among Widget yes immutable Immutable , and Widget How to update and redraw , This is inseparable Element and RenderObject; Side dishes: let's have a brief look at Element Little knowledge about ;
【Flutter project 】101 What is the Flutter Elements ?#yyds Dry inventory #_Flutter Side dish

Element

      Element yes Widget stay UI An instantiated object at the specific location of the tree ;UI View stay Element A real... Will be built in the hierarchy Element Tree, Is the real view tree structure ;Element As Widget and RenderObject The coordinator between , And according to Widget To complete the operation of adding, deleting and modifying nodes ;
【Flutter project 】101 What is the Flutter Elements ?#yyds Dry inventory #_Flutter Side dish _02

Source code analysis

      Element The source code involved is long , The side dishes only learn about specific methods and life cycles ;

Life cycle

enum _ElementLifecycle {
  initial,
  active,
  inactive,
  defunct,
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

      Element The life cycle mainly includes the following parts , Namely initial initialization ,active Active state ,inactive Inactive status and defunct Failure state ;

For methods

1. createElement
Element(Widget widget) : assert(widget != null), _widget = widget;

     
  • 1.

       Create one using the specified Widget As its configuration Element; adopt Widget call Widget.createElement To create Element, As Element Initial position ;

2. mount
@mustCallSuper
void mount(Element parent, dynamic newSlot) {
    ...
    _parent = parent;
    _slot = newSlot;
    _depth = _parent != null ? _parent.depth + 1 : 1;
    _active = true;
    if (parent != null) 
      _owner = parent.owner;
    if (widget.key is GlobalKey) {
      final GlobalKey key = widget.key;
      key._register(this);
    }
    _updateInheritance();
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

      mount() We'll put the new Element Add to the specified parent slot In the slot tree , By calling attachRenderObject Add to the rendering tree ;

3. update
@protected
Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
    if (newWidget == null) {
      if (child != null) deactivateChild(child);
      return null;
    }
    if (child != null) {
      if (child.widget == newWidget) {
        if (child.slot != newSlot) updateSlotForChild(child, newSlot);
        return child;
      }
      if (Widget.canUpdate(child.widget, newWidget)) {
        if (child.slot != newSlot) updateSlotForChild(child, newSlot);
        child.update(newWidget);
        return child;
      }
      deactivateChild(child);
      assert(child._parent == null);
    }
    return inflateWidget(newWidget, newSlot);
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

      updateChild yes Element The core method of , Whenever you need to add , modify , Delete child child It will call ; Mainly based on Widget The change of is used for Element Update , And then update UI Trees ;

newWidget == nullnewWidget != null
child == nullReturns null.Returns new [Element].
child != nullOld child is removed, returns null.Old child updated if possible, returns child or new [Element].
  1. When updated Widget by null when , The corresponding child node has been removed , If at present child Not for null, directly remove fall ;
  2. When updated Widget Not for null And the current child by null when , Explain new Widget It's new , be inflateWidget Create child nodes ;
  3. When updated Widget Not for null And the current child Not for null When the node exists , if child.widget == newWidget It indicates that there is no change before and after the child node , if child.slot != newSlot It indicates that the child node has moved its position between brother nodes , here updateSlotForChild Update node location ; Otherwise, return directly to the child node ;
  4. When updated Widget Not for null And the current child Not for null When the node exists , if Widget.canUpdate by true The instructions can be used newWidget Modify child nodes , Call directly update Update can ; Otherwise, remove the child node first and then pass through newWidget Create a new child node ; among canUpdate Mainly to judge the old and new Widget Of key and runtimeType Is it consistent ;
4. deactivate
@protected
void deactivateChild(Element child) {
    child._parent = null;
    child.detachRenderObject();
    owner._inactiveElements.add(child); // this eventually calls child.deactivate()
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

      deactivateChild Will specify Element Inactive... Has been detected Element In the list , And remove the rendered object from the render tree ; This method can prevent Element Become its subclass ;

5. activate
@mustCallSuper
void activate() {
    final bool hadDependencies = (_dependencies != null && _dependencies.isNotEmpty) || _hadUnsatisfiedDependencies;
    _active = true;
    _dependencies?.clear();
    _hadUnsatisfiedDependencies = false;
    _updateInheritance();
    
    if (_dirty)
      owner.scheduleBuildFor(this);
    if (hadDependencies)
      didChangeDependencies();
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

      activate() For will Element When merging back into the tree , The framework will start from inactive Inactive Element Delete the element from the list , And this element calls activate And will Element Add the rendered object to the render tree ;

6. unmount
@mustCallSuper
void unmount() {
    if (widget.key is GlobalKey) {
        final GlobalKey key = widget.key;
        key._unregister(this);
    }
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

      unmount() To call... When the framework will never be reactivated ; In order to avoid repeated creation in one animation execution , Remove specific Element when , Inactive Element Will be retained at the last frame of the current animation process , If you haven't become active by the end of the animation , Call unmount() Will be Element Completely remove ;

Corresponding relation

  1. Widget.createElement by initial Initialization life cycle from nothing ;
  2. mount by initial Initialization status to active Transition from active state to life cycle ;
  3. update Only in active Only when it is active ;
  4. deactivate by active Active to inactive Inactive life cycle transition ;
  5. activate by inactive Inactive to active Life cycle transition of active state ;
  6. unmount by inactive Inactive to defunct Transition of failure state life cycle ;

Subclass Element

      Element There are mainly composite classes ComponentElement And rendering classes RenderObjectElement Two subclasses ;

ComponentElement

      ComponentElement Is a composite class Element, It mainly includes the following StatelessElement / StatefulElement / ProxyElement Subclass ; Each of them Element Are all with Widget Corresponding ;

StatelessElement
class StatelessElement extends ComponentElement {
  StatelessElement(StatelessWidget widget) : super(widget);

  @override
  StatelessWidget get widget => super.widget;

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

  @override
  void update(StatelessWidget newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  }
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

      StatelessElement Relatively simple , Mainly rewriting update() When changes are needed rebuild() that will do ;

StatefulElement
@override
void update(StatefulWidget newWidget) {
    super.update(newWidget);
    final StatefulWidget oldWidget = _state._widget;
    _dirty = true;
    _state._widget = widget;
    try {
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(true);
      final dynamic debugCheckForReturnedFuture = _state.didUpdateWidget(oldWidget) as dynamic;
    } finally {
      _debugSetAllowIgnoredCallsToMarkNeedsBuild(false);
    }
    rebuild();
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

      StatefulElement It's corresponding to StatefulWidget Of , Including complete Element Life cycle , Which will be updated when updating State and rebuild();

ProxyElement
abstract class ProxyElement extends ComponentElement 
  ProxyElement(ProxyWidget widget) : super(widget);

  @override
  ProxyWidget get widget => super.widget;

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

  @override
  void update(ProxyWidget newWidget) {
    final ProxyWidget oldWidget = widget;
    assert(widget != null);
    assert(widget != newWidget);
    super.update(newWidget);
    assert(widget == newWidget);
    updated(oldWidget);
    _dirty = true;
    rebuild();
  }

  @protected
  void updated(covariant ProxyWidget oldWidget) {
    notifyClients(oldWidget);
  }

  @protected
  void notifyClients(covariant ProxyWidget oldWidget);
}

     
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

      ProxyElement As an abstract class , Its subclass is ParentDataElement and InheritedElement; When Widget Call when updating update();notifyClients() For old and new Widget Call... When it has indeed changed ;

RenderObjectElement

      RenderObjectElement For render type Element The corresponding is RenderObjectWidget;RenderObjectElement As an abstract class, it also inherits Element All life cycle approaches ;

       Most of the RenderObjectElement Each corresponds to one RenderObject That is, there is only one child node , for example RootRenderObjectElement / SingleChildRenderObjectElement; But there are also special , Such as LeafRenderObjectElement Subclasses have no child nodes , as well as MultiChildRenderObjectElement Subclasses can have multiple sub sections ;


      Element As Widget and RenderObject Our collaborators play a connecting role ; I'll learn it in the next article RenderObject; The understanding of the source code is not deep enough , If there is a mistake , Please give me more guidance !

source : Little monk aze

copyright notice
author[51CTO],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/119/202204290902061091.html

Random recommended