[Flutter笔记]Widget/Element/RenderObject

1,663 阅读3分钟

[Flutter笔记]Widget/Element/RenderObject

简单示例

Opacity

TODO

Shimmer

juejin.cn/post/684490…

RenderShimmer 聚合(注1)于 Shimmer,即Shimmer(作为Widget)负责生成RenderShimmer(作为RenderObject)

Shimmer

classDiagram
  SingleChildRenderObjectWidget <|-- Shimmer
  RenderProxyBox <|-- RenderShimmer
  Shimmer o.. RenderShimmer

原理讲解

Widget

StatelessWidget/StatefulWidget

StatelessWidget/StatefulWidget

classDiagram
    Widget <|-- StatelessWidget
    Widget <|-- StatefulWidget
    Widget: +Element createElement()
    class StatelessWidget {
        +StatelessElement createElement()
        +Widget build(BuildContext)
    }
    class StatefulWidget {
        +StatefulElement createElement()
        +State_T createState()
    }
    class State_T {
        +Widget widget
        +BuildContext context
        +bool mounted
        +initState()
        +didUpdateWidget(T)
        +reassemble()
        +setState(VoidCallback)
        +deactivate()
        +dispose()
        +Widget build(BuildContext) 
        +didChangeDependencies()
    }

ProxyWidget

ProxyWidget

classDiagram
  Widget <|-- ProxyWidget
  Widget: +Element createElement()
  ProxyWidget: +Widget child
  ProxyWidget <|-- ParentDataWidget_T
  class ParentDataWidget_T {
    +ParentDataElement_T createElement()
    +applyParentData(RenderObject)
  }
  ProxyWidget <|-- InheritedWidget
  class InheritedWidget {
    +InheritedElement createElement()
    +bool updateShouldNotify(InheritedWidget)
  }

RenderObjectWidget

RenderObjectWidget

classDiagram
  Widget <|-- RenderObjectWidget
  Widget: +Element createElement()
  class RenderObjectWidget {
    +RenderObjectElement createElement()
    +RenderObject createRenderObject(BuildContext)
    +updateRenderObject(BuildContext, RenderObject)
    +didUnmountRenderObject(RenderObject)
  }
  RenderObjectWidget <|-- LeafRenderObjectWidget
  class LeafRenderObjectWidget {
    +LeafRenderObjectElement createElement()
  }
  RenderObjectWidget <|-- SingleChildRenderObjectWidget
  class SingleChildRenderObjectWidget {
    +Widget child
    +SingleChildRenderObjectElement createElement()
  }
  RenderObjectWidget <|-- MultiChildRenderObjectWidget
  class MultiChildRenderObjectWidget {
    +List<Widget> children
    +MultiChildRenderObjectElement createElement()
  }

Element

BuildContext

classDiagram
    class BuildContext {
        +Widget widget
        +BuildOwner owner
        +Size size

        +RenderObject findRenderObject()
        (...)
        +InheritedWidget dependOnInheritedElement(InheritedElement, _Object_)
        +T dependOnInheritedWidgetOfExactType(_Object_)
        +InheritedElement getElementForInheritedWidgetOfExactType()
        +T findAncestorWidgetOfExactType()
        +T findAncestorStateOfType()
        +T findRootAncestorStateOfType()
        +T findAncestorRenderObjectOfType()
        +visitAncestorElements(Function)
        +visitChildElements(ElementVisitor)
    }

Element

classDiagram
    BuildContext <|-- Element
    class Element {
        -Element _parent
        +dynamic slot
        +Widget widget
        +BuildOwner owner
        +RenderObject renderObject
        +Size size
        +bool dirty
        
        +reassemble()
        +visitChildren(ElementVisitor)
        +visitChildElements(ElementVisitor)
        +Element updateChild(Element, Widget, dynamic)
        +mount(Element, dynamic)
        +update(Widget)
        +updateSlotForChild(Element, dynamic)
        +detachRenderObject()
        +attachRenderObject(dynamic)
        +Element inflateWidget(Widget, dynamic)
        +deactivateChild(Element)
        +forgetChild(Element)
        +activate()
        +deactivate()
        +unmount()
        (...)
        +didChangeDependencies()
        +markNeedsBuild()
        +rebuild()
        +performRebuild()
    }

StatelessElement/StatefulElement

StatelessElement/StatefulElement

classDiagram
    Element <|-- ComponentElement
    class ComponentElement {
        +mount(Element, dynamic)
        +performRebuild()
        +Widget build()
        +visitChildren(ElementVisitor)
        +forgetChild(Element)
    }
    ComponentElement <|-- StatelessElement
    ComponentElement <|-- StatefulElement
    class StatelessElement {
        +StatelessWidget widget
        +Widget build()
        +update(StatelessWidget)
    }
    class StatefulElement {
        +State_T state
        +Widget build()
        +reassemble()
        +update(StatefulWidget)
        +activate()
        +deactivate()
        +unmount()
        +InheritedWidget dependOnInheritedElement(Element, _Object_)
        +didChangeDependencies()
    }

ProxyElement

ProxyElement

classDiagram
    ComponentElement <|-- ProxyElement
    class ProxyElement {
        +ProxyWidget widget
        +Widget build()
        +update(ProxyWidget)
        +updated(ProxyWidget)
        +notifyClients(ProxyWidget)
    }

RenderObjectElement

RenderObjectElement

classDiagram
    Element <|-- RenderObjectElement
    class RenderObjectElement {
        +RenderObjectWidget widget
        +RenderObject renderObject
        +mount(Element, dynamic)
        +performRebuild()
        +List<Element> updateChildren(List<Element>, List<Widget>, _Set<Element>_)
        +deactivate()
        +unmount()
        +attachRenderObject(dynamic)
        +detachRenderObject()
        +insertChildRenderObject(RenderObject, dynamic)
        +moveChildRenderObject(RenderObject, dynamic)
        +removeChildRenderObject(RenderObject)
    }
    RenderObjectElement <|-- RootRenderObjectElement
    RenderObjectElement <|-- LeafRenderObjectElement
    RenderObjectElement <|-- SingleChildRenderObjectElement
    RenderObjectElement <|-- MultiChildRenderObjectElement
    class RootRenderObjectElement {
        +assignOwner(BuildOwner)
        +mount(Element, dynamic)
    }
    class SingleChildRenderObjectElement {
        +SingleChildRenderObjectWidget widget
        +visitChildren(ElementVisitor)
        +forgetChild(Element)
        +mount(Element, dynamic)
        +update(SingleChildRenderObjectWidget)
        +insertChildRenderObject(RenderObject, dynamic)
        +removeChildRenderObject(RenderObject)
    }
    class MultiChildRenderObjectElement {
        +MultiChildRenderObjectWidget widget
        +Iterable<Element> children
        +insertChildRenderObject(RenderObject, dynamic)
        +moveChildRenderObject(RenderObject, dynamic)
        +removeChildRenderObject(RenderObject)
        +visitChildren(ElementVisitor)
        +forgetChild(Element)
        +mount(Element, dynamic)
        +update(SingleChildRenderObjectWidget)
    }

RenderObject

RenderObject

classDiagram
    RenderObject <|-- RenderView
    RenderObject <|-- RenderBox
    RenderObject <|-- RenderSliver
    RenderObject <|-- RenderAbstractViewport
    RenderObject <|-- RenderObjectWithChildMixin
    RenderObject <|-- ContainerRenderObjectMixin

RenderView

RenderView

classDiagram
    class RenderView {
        +Size size
        +ViewConfiguration configuration
        +Rect paintBounds
        +prepareInitialFrame()
        +performLayout()
        +paint(PaintingContext, Offset)
        +applyPaintTransform(RenderBox, Matrix4)
        +compositeFrame()
    }

RenderBox

RenderBox

classDiagram
    class RenderBox {
        +bool hasSize
        +Size size
        +BoxConstraints constraints
        +Rect paintBounds

        +setupParentData(RenderObject)
        (...)
        +double getMinIntrinsicWidth(double)
        +double computeMinIntrinsicWidth(double)
        +double getMaxIntrinsicWidth(double)
        +double computeMaxIntrinsicWidth(double)
        +double getMinIntrinsicHeight(double)
        +double computeMinIntrinsicHeight(double)
        +double getMaxIntrinsicHeight(double)
        +double computeMaxIntrinsicHeight(double)
        (...)
        +double getDistanceToBaseline(TextBaseline, _bool_)
        +double getDistanceToActualBaseline(TextBaseline)
        +double computeDistanceToActualBaseline(TextBaseline)
        (...)
        +markNeedsLayout()
        +performResize()
        +performLayout()
        +hitTest(BoxHitTestResult, Offset)
        +hitTestSelf(Offset)
        +hitTestChildren(BoxHitTestResult, Offset)
        +applyPaintTransform(RenderObject, Matrix4)
        +Offset globalToLocal(Offset, _RenderObject_)
        +Offset localToGlobal(Offset, _RenderObject_)
        +handleEvent(PointerEvent, BoxHitTestEntry)
    }

RenderSliver

RenderSliver

classDiagram
    class RenderSliver {
        +SliverConstraints constraints
        +SliverGeometry geometry
        +Rect paintBounds
        +double centerOffsetAdjustment
        +performResize()
        (...)
        +hitTest(SliverHitTestResult, double, double)
        +hitTestSelf(double, double)
        +hitTestChildren(SliverHitTestResult, double, double)
        (...)
        +double calculatePaintOffset(SliverConstraints, double, double)
        +double calculateCacheOffset(SliverConstraints, double, double)
        +double childMainAxisPosition(RenderObject)
        +double childCrossAxisPosition(RenderObject)
        +double childScrollOffset(RenderObject)
        +applyPaintTransform(RenderObject, Matrix4)
        +getAbsoluteSizeRelativeToOrigin()
        +Size getAbsoluteSize()
        +handleEvent(PointerEvent, SliverHitTestEntry)
    }

RenderAbstractViewport

RenderAbstractViewport

classDiagram
    class RenderAbstractViewport {
        +RevealedOffset getOffsetToReveal(RenderObject, double, _Rect_)
    }
    RenderAbstractViewport <|-- RenderViewportBase
    RenderAbstractViewport <|--RenderListWheelViewport
    RenderAbstractViewport <|-- _RenderSingleChildViewport

RenderObjectWithChildMixin

RenderObjectWithChildMixin

classDiagram
    class RenderObjectWithChildMixin {
        +ChildType child
        +attach(PipelineOwner)
        +detach()
        +redepthChildren()
        +visitChildren(RenderObjectVisitor)
    }

ContainerRenderObjectMixin

ContainerRenderObjectMixin

classDiagram
    class ContainerRenderObjectMixin {
        +int childCount
        +ChildType firstChild
        +ChildType lastChild
        +insert(ChildType child, _ChildType)
        +add(ChildType)
        +addAll(List<ChildType>)
        +remove(ChildType)
        +removeAll()
        +move(ChildType child, ChildType)
        +attach(PipelineOwner)
        +detach()
        +redepthChildren()
        +visitChildren(RenderObjectVisitor)
        +ChildType childBefore(ChildType)
        +ChildType childAfter(ChildType)
    }

复杂示例

Slider

TODO

参考

Insider Flutter

深入了解Flutter界面开发(强烈推荐)

深入绘制原理

RenderObject与RenderBox

附注

  1. UML关系:

学生与老师,学生不是老师的一部分

干电池与收音机,电池是收音机一部分,但也能用于其他电器

内置电池与手机,电池是手机不可分割一部分****