FlutterGoogle开发的构建高性能UI界面的框架。在Flutter中一切都是Widget

渲染组成

Widget

Widget效率英文翻译是对用户界面的一种不可变的描述。由于Widget是不可变的,当App进行交互的时候,我们的界面要进行变动,是怎么做到的呢?

实际上,Flutter由3种树Widget Tre枸杞eE宫颈癌lement TreeRenderObject Tree。Flutter通过结合这三颗树,更加高效的渲染UI界面elementary

使用Widget,可以声明我们想要的UI样式,配置样式属性信息。可以说是WidgetElement的一个配置描述。Widget会被映射为一个Element对象。

Widget它们本身没有可elementary翻译变的状态,如果我们想让Widget有可变的状态,可以使用StatefulWidgetStatefulWidget会创建一个Stateapplication象,并将State对象插入到Element树中。

同一个Wi效率是什么意思dget可能会被多次移除和添加,同样的,同一个龚俊Element对象也会被多次在Element树中移除和添加。

Element

Element是用来描述Widget在树中位置的,记录了其上google谷歌搜索主页下级关系。它是可变的,用来管理UI的更新和变化。我们可以认为Element是来管理Widget的生命周期的。实际上Widget是没有生命周期的,效率英文翻译Element有生elements中文翻译命周期的,Element的生龚俊命周期也代表了WidgGoogleet对象是否还在树中。

RenderObject

RenderObject负责设置大小,布局和绘制UI的,Flutter通过参照Render tree进行UI绘制。

通过以上我们知道由Widget负责配置信息,Element负责生命周期Element,RenderObject负责绘制。那么Flutter渲染Wigoogle服务框架dget也分为3部分:设置配置信息,控制生命周期和绘制

Flutter是如何渲染Widget的

  • 1,通过设置Widgetpropertiesmethod,来配置UI的信息。
  • 2,通过Element来控制UI对象的生命周期,并且管理Element对象效率的父子关系。
  • 3,公司让员工下班发手机电量截图通过RenderObject,每个componet都有paint方法,通过约束和大小确定位置关系,并开始绘制

Flutter是如何渲染Widget的

Source St工商银行ep By Step

3颗树的创appointment建流程

我们来看如下代码:

Widget build(BuildContext context) {
  return Center(
    child: RichText(
      text: const TextSpan(text: "Rich Text"),
    ),
  );
}

当创建RichTextWidget的时候, 1,会创建 MultiChildRenderObjectElement对象。

class RichText extends MultiChildRenderObjectWidget {
    //....
}
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {
    ....
    @override
    MultiChildRenderObjectElement createElement() => MultiChildRenderObjectElement(this);
}

2,第二步,在mount方法中,创建RenderOgoogleplaybject对象。

abstract class RenderObjectElement extends Element {
  ......
  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
     ......
    _renderObject = widget.createRenderObject(this);
     ......
    attachRenderObject(newSlot);
    _dirty = false;
  }

2.1,将Widget中的配置信息(属性),赋值给RenderObject对象。

MultiChildRenderObjectWidget:
@override
RenderParagraph createRenderObject(BuildContext context) {
  assert(textDirection != null || debugCheckHasDirectionality(context));
  return RenderParagraph(text,
    textAlign: textAlign,
    textDirection: textDirection ?? Directionality.of(context),
    softWrap: softWrap,
    overflow: overflow,
    textScaleFactor: textScaleFactor,
    maxLines: maxLines,
    strutStyle: strutStyle,
    textWidthBasis: textWidthBasis,
    textHeightBehavior: textHeightBehavior,
    locale: locale ?? Localizations.maybeLocaleOf(context),
  );
}

通过以上步骤,我们就得到了MultiChildRenderObjectWidget、MultiC效率符号hildRenderObjectElement 和 RenderParagraph

更新子部件

有时候我们需要根据不同的状态显示不同UI界面,这时候,就会去更新子部件,我们看如下代码

Widget build(BuildContext context) {
  return Center(
    child: RichText(
      text: reverse
          ? const TextSpan(text: "Rich Text Two")
          : const TextSpan(text: "Rich Text"),
    ),
  );
}

reverse值更改的时候,在appear下一次rebuild()的过程中,将 TextSpan(text: "Rich Text Two")加入到Widget树,将原来的TextSpan效率是什么意思Widget树中移除,与相同位置的Widget进行比较,通过canUpdate方法判断是否可以更新

Widget:
static bool canUpdate(Widget oldWidget, Widget newWidget) {
  return oldWidget.runtimeType == newWidget.runtimeType
      && oldWidget.key == newWidget.key;
}

两个TextSpaelement滑板n具有相同的runtimeType,且他俩的key值都为null,返回Yes

然后执行 widget.updateRenderObject(this, renderObject); 更新RenderObject信息。

Widget:
@override
void updateRenderObject(BuildContext context, RenderParagraph renderObject) {
  assert(textDirection != null || debugCheckHasDirectionality(context));
  renderObject
    ..text = text
    ..textAlign = textAlign
    ..textDirection = textDirection ?? Directionality.of(context)
    ..softWrap = softWrap
    ..overflow = overflow
    ..textScaleFactor = textScaleFactor
    ..maxLines = maxLines
    ..strutStyle = strutStyle
    ..textWidthBasis = textWidthBasis
    ..textHeightBehavior = textHeightBehavior
    ..locale = locale ?? Localizations.maybeLocaleOf(context);
}

approach样,RenderObject树中的信息就会被更新。通过重用RenderObject对象,就大大的提高了效率。毕竟,新建一个对象的开销非常大。

参考

Ho宫颈癌w Flutter Render Widgets