Code前端首页关于Code前端联系我们

Flutter 开发实践实践六:深入 Widget 原理

terry 2年前 (2023-09-23) 阅读数 65 #移动小程序

什么是 Widget?这是“著名”答案:小部件不是真正的渲染对象。是的,实际上 Flutter 中的渲染经历了从WidgetElementRenderObject的过程。

我们都知道Widget是不可变的,那么Widget是如何让图片不可变的呢?上面我们知道,Widget必须转换为Element才能渲染。从下图的注释中可以看到,其实Widget只是对Element的配置的描述,告诉Element如何创建这个例子。 Flutter开发实战六:深入Widget原理

那么Widgets和Elements之间的正确关系是怎样的呢?从上图的注释中也可以看出: Widget 和 Element 之间是一对多的关系。其实渲染树就是一棵由Element节点组成的树,而Widget就是一个配置文件,在树的很多部分都可以复用,对应各种Element对象。

然后RenderObject?以上两者有何关系?从源代码注释中提到渲染树中的对象,我们可以看到RenderObject是实际的渲染对象,通过Element源代码我们可以看到:Element持有RenderObject和小部件。

Flutter开发实战六:深入Widget原理

结合下图,我们可以大致总结一下三者之间的关系: Widget配置文件生成Element,然后创建RenderObject并关联内部Element renderObject最后Flutter通过RenderObject Data打下get出来并拉动。 理论上,你也可以认为RenderObject是最后给予Flutter的渲染数据。保存大小、位置等信息,Flutter用它来绘制图像。Flutter开发实战六:深入Widget原理

说到RenderObject,就必须要说Render盒子渲染对象,作为2D笛卡尔系中出现的♶笛卡尔坐标。注释代码,它继承了基本布局和图像功能RenderObject,并实现了“笛卡尔坐标系”:以Top和Left为基点,通过宽度和高度两个轴实现布局和嵌套。 。

Render Box避免了直接使用RenderObject的烦人场景,其中Render Box❀的布局和尺寸计算在♻❀和中进行 执行调整大小() 为了克服这两种方法,我们往往会选择继承Render盒子来实现定制。

根据上面的情况,我们知道:

  • Widget只是一个显示数据的配置,所以有点轻量。 Flutter也对Widget做了一定的优化,这样每次状态发生变化时,都会导致Widget的重建问题不那么严重。
  • RenderObject不同。RenderObject参与布局、计算、绘图等过程。每次重新创建所有内容的成本会很高。

因此 Widget 对于每次是否应该创建新的 Element 和 RenderObject 对象都做出了适当的决定,以方便重用,例如:在 newWidgetoldWidgetFlutter开发实战六:深入Widget原理

key相同,newWidget将被选择更新现有的Element对象,否则将创建一个新的Element。

由此可以看出:Widget会重新生成,Element树和RenderObject树不会重新生成。

看到这里,我们扯个题外话:一般如何获取布局尺寸和位置?

首先,我们需要使用前面提到的GlobalKey。使用按钮从控制对象中获取BuildContext,我们也知道BuildContext实现其实是Element, catch RenderObject。所以,我们所知道的RenderObject实际上是Render盒子。然后通过Render盒子就知道大小和位置了。

  showSizes() {
    RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject();
    print(renderBoxRed.size);
  }

  showPositions() {
    RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject();
    print(renderBoxRed.localToGlobal(Offset.zero));
  }

作者:连毛德小果
链接:https://juejin.im/post/5c7e853151882549664b0543
来源:掘金商业转载请联系作者授权。非商业转载请注明出处。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门