Flutter随笔

Flutter Element笔记

2020-09-16  本文已影响0人  嘛尼嘛哄

Element主要分为2类

  1. ComponentElement: 合成其它的Element, 它的子类又StatelessElement,StatefulElement,ProxyElement, 其中StatelessElement和StatefulElement主要用于组建有状态和无状态的widget,ProxyElement则是用于更新依赖,传递数据,局部状态管理。
  2. RenderObjectElement
    提供RenderObject的配置信息,用于创建对应结点的RenderObject

Element家族图普

DiagnosticableTree (diagnostics.dart)
    Element (framework.dart)
        ComponentElement (framework.dart)
            StatelessElement (framework.dart)
            StatefulElement (framework.dart)
            ProxyElement (framework.dart)
                InheritedElement (framework.dart)
                ParentDataElement (framework.dart)
        RenderObjectElement (framework.dart)
            SliverMultiBoxAdaptorElement (sliver.dart)
                _SliverPrototypeExtentListElement (sliver_prototype_extent_list.dart)
            _TableElement (table.dart)
            _LayoutBuilderElement (layout_builder.dart)
            ListWheelElement (list_wheel_scroll_view.dart)
            _SliverPersistentHeaderElement (sliver_persistent_header.dart)
            _CupertinoAlertRenderElement (action_sheet.dart)
            _CupertinoDialogRenderElement (dialog.dart)
            _RenderDecorationElement (input_decorator.dart)
            _ListTileElement (list_tile.dart)
            _RenderChipElement (chip.dart)
            SingleChildRenderObjectElement (framework.dart)
                _OffstageElement (basic.dart)
                _SliverOffstageElement (sliver.dart)
            MultiChildRenderObjectElement (framework.dart)
                _ViewportElement (viewport.dart)
                _TheatreElement (overlay.dart)
                _TextSelectionToolbarItemsElement (text_selection.dart)
            LeafRenderObjectElement (framework.dart)
            RootRenderObjectElement (framework.dart)
                RenderObjectToWidgetElement (binding.dart)

Element {

  1. 继承于BuildContext, 同时和Widget绑定
    Element > DiagnosticableTree > BuildContext
Element(Widget widget)
StatelessElement createElement() => StatelessElement(this);
  1. slot描述了 Element在Tree的位置,在BuilderOwner装配的时候回根据slot决定Element在tree中的位置
//提供给parentElement,用于确定他在child list中的位置
dynamic get slot => _slot;
int get depth => _depth;

set slot => _slot;
  static int _sort(Element a, Element b) {
    if (a.depth < b.depth)
      return -1;
    if (b.depth < a.depth)
      return 1;
    if (b.dirty && !a.dirty)
      return -1;
    if (a.dirty && !b.dirty)
      return 1;
    return 0;
  }

void mount(Element parent, dynamic newSlot)
  1. 通过BuilderOwner可以对ElementTree中的元素更新
  BuildOwner get owner => _owner;
  ...
    void reassemble() {
    markNeedsBuild();
    visitChildren((Element child) {
      child.reassemble();
    });
  }
  1. 获取当前Element下对应的RenderObject(最近的一个RenderObject)
class Element 
...
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;
  }

abstract class ComponentElement extends Element
   ...
    @override
  void visitChildren(ElementVisitor visitor) {
    if (_child != null)
      visitor(_child);
  }
  1. 管理Child RenderObject,
  void detachRenderObject() {
    visitChildren((Element child) {
      child.detachRenderObject();
    });
    _slot = null;
  }
  //Add [renderObject] to the render tree at the location specified by [slot].
  void attachRenderObject(dynamic newSlot) {
    assert(_slot == null);
    visitChildren((Element child) {
      child.attachRenderObject(newSlot);
    });
    _slot = newSlot;
  }
  1. Globalkey绑定,缓存带有GlobalKey的Element
  void mount(Element parent, dynamic newSlot)
  ......
  if (key is GlobalKey) {
      key._register(this);
    }

  void unmount() {
    ...
    if (key is GlobalKey) {
      key._unregister(this);
    }
    ...
  }
  1. Global Key
Element inflateWidget(Widget newWidget, dynamic newSlot) {
    assert(newWidget != null);
    final Key key = newWidget.key;
    if (key is GlobalKey) {
      final Element newChild = _retakeInactiveElement(key, newWidget);
      ...
    }
    final Element newChild = newWidget.createElement();
    ...
  }

总结

BuildContext

//当前Context的配置信息
Widget get widget;
//当前Context的builderOwner,用于管理当前Context的渲染管道
BuildOwner get owner;
//用于查找当前关联的widget的 renderObject,如果找不到就找到下一级最近的
RenderObject findRenderObject();
//通过findRenderObject查找到的RenderObject在窗口中的大小
Size get size;
//注册当前的buildContext到它的上一级的BuildContext中,当`anccestor`的widget变化时会触发当前这个buildContext rebuilt方法
//返回值 InheritedWidget是ancestor.widget
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
//返回当前Context最近的一个`InheritedWidget`
T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object aspect });

ComponentElement

StatelessElement

class StatelessElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  StatelessElement(StatelessWidget widget) : super(widget);

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

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

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

StatefulElement

class StatefulElement extends ComponentElement {
  //根据给定的StatefulWidget配置信息创建Element
  StatefulElement(StatefulWidget widget)
      : _state = widget.createState(),
    _state._widget = widget;
  ...
  
  //构建对应state状态的widget
  @override
  Widget build() => _state.build(this);

  @override
  void reassemble() {
    state.reassemble();  //state重建
    super.reassemble();
  }

  @override
  void _firstBuild() {
     _state.didChangeDependencies();
    super._firstBuild();
  }

  @override
  void performRebuild() {
    if (_didChangeDependencies) {
      _state.didChangeDependencies();
      _didChangeDependencies = false;
    }
    super.performRebuild();
  }

  @override
  void update(StatefulWidget newWidget) {
    super.update(newWidget);
    final StatefulWidget oldWidget = _state._widget;
    ...
    rebuild();
  }

  @override
  void activate() {
    super.activate();
    assert(_active); // otherwise markNeedsBuild is a no-op
    markNeedsBuild();
  }

  @override
  void deactivate() {
    _state.deactivate();
    super.deactivate();
  }
  
  //Element移除时,释放state资源
  @override
  void unmount() {
    super.unmount();
    _state.dispose();
    _state._element = null;
    _state = null;
  }

 
  @override
  InheritedWidget inheritFromElement(Element ancestor, { Object aspect }) {
    return dependOnInheritedElement(ancestor, aspect: aspect);
  }

  @override
  InheritedWidget dependOnInheritedElement(Element ancestor, { Object aspect }) {
    ...
    return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
  }

  //依赖更新
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _didChangeDependencies = true;
  }
}

ProxyElement

abstract class ProxyElement extends ComponentElement 
...
  void update(ProxyWidget newWidget) {
    final ProxyWidget oldWidget = widget;
     ..
    updated(oldWidget);
     ...
    rebuild();
  }
void updated(covariant ProxyWidget oldWidget) {
    notifyClients(oldWidget);
  }

ParentDataElement

区别在于如果是ParentDataElement会调用所有的child._updateParentData
所有的child都能更新

class ParentDataElement<T extends ParentData> extends ProxyElement {
  ...
    void notifyClients(ParentDataWidget<T> oldWidget) {
    _applyParentData(widget);
  }
  ...
  void _applyParentData(ParentDataWidget<T> widget) {
    void applyParentDataToChild(Element child) {
      if (child is RenderObjectElement) {
        child._updateParentData(widget);
      } else {
        assert(child is! ParentDataElement<ParentData>);
        child.visitChildren(applyParentDataToChild);
      }
    }
    visitChildren(applyParentDataToChild);
  }

InheritedElement

class InheritedElement extends ProxyElement {
  /// Creates an element that uses the given widget as its configuration.
  InheritedElement(InheritedWidget widget) : super(widget);
Map<Element, Object> _dependents = HashMap<Element, Object>();
...
  @protected
  Object getDependencies(Element dependent) {
    return _dependents[dependent];
  }
    @protected
  void setDependencies(Element dependent, Object value) {
    _dependents[dependent] = value;
  }
    @protected
  void updateDependencies(Element dependent, Object aspect) {
    setDependencies(dependent, null);
  }
   @protected
  void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
    dependent.didChangeDependencies();
  }
    @override
  void updated(InheritedWidget oldWidget) {
    if (widget.updateShouldNotify(oldWidget))
      super.updated(oldWidget);
  }
    @override
  void notifyClients(InheritedWidget oldWidget) {
      ...
      notifyDependent(oldWidget, dependent);
    }
  }
  

update widget -> notifiyClients -> notifyDependent -> didChangeDependencies

@override
  void _updateInheritance() {
    assert(_active);
    final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
    if (incomingWidgets != null)
      _inheritedWidgets = HashMap<Type, InheritedElement>.from(incomingWidgets);
    else
      _inheritedWidgets = HashMap<Type, InheritedElement>();
    _inheritedWidgets[widget.runtimeType] = this;
  }

RenderObjectElement

  void mount(Element parent, dynamic newSlot) {
    super.mount(parent, newSlot);
     ...
    _renderObject = widget.createRenderObject(this);
     attachRenderObject(newSlot);
     ...
//通过递归调用 `ancestor._parent`(Element中_parent)来获取anestor `RenderObjectElemenet`
  RenderObjectElement _findAncestorRenderObjectElement() {
    Element ancestor = _parent;
    while (ancestor != null && ancestor is! RenderObjectElement)
      ancestor = ancestor._parent;
    return ancestor as RenderObjectElement;
  }
  //同上,递归调用获取anccestor为`ParenetDataElement<ParentData>`的Element
  ParentDataElement<ParentData> _findAncestorParentDataElement()

  mount(Element parent, dynamic newSlot)
  unmount()
  update(covariant RenderObjectWidget newWidget) 
  _updateSlot(dynamic newSlot) 
  performRebuild
  //用于MultiRenderObject来更新数据
  List<Element> updateChildren(List<Element> oldChildren, List<Widget> newWidgets, { Set<Element> forgottenChildren })
  attachRenderObject(dynamic newSlot)
  _updateParentData

RootRenderObjectElement>RenderObjectElement

RootRenderObjectElement(RenderObjectWidget widget) : super(widget);
mount(Element parent, dynamic newSlot) 

LeafRenderObjectElement>RenderObjectElement

forgetChild(Element child)
insertChildRenderObject(RenderObject child, dynamic slot)
moveChildRenderObject(RenderObject child, dynamic slot) 
removeChildRenderObject(RenderObject child)

SingleChildRenderObjectElement > RenderObjectElement

visitChildren(ElementVisitor visitor)
forgetChild(Element child)
mount(Element parent, dynamic newSlot)
update(SingleChildRenderObjectWidget newWidget) 
insertChildRenderObject(RenderObject child, dynamic slot)
//无法移动
 void moveChildRenderObject(RenderObject child, dynamic slot) {
    assert(false);
  }
removeChildRenderObject(RenderObject child)

MultiChildRenderObjectElement > RenderObjectElement

MultiChildRenderObjectWidget get widget => super.widget as MultiChildRenderObjectWidget;
Iterable<Element> get children => _children.where((Element child) => !_forgottenChildren.contains(child));
insertChildRenderObject(RenderObject child, IndexedSlot<Element> slot)
moveChildRenderObject(RenderObject child, IndexedSlot<Element> slot)
removeChildRenderObject(RenderObject child)
visitChildren(ElementVisitor visitor)
forgetChild(Element child)
mount(Element parent, dynamic newSlot)
update(MultiChildRenderObjectWidget newWidget)
上一篇 下一篇

猜你喜欢

热点阅读