[Flutter翻译]Flutter Rendering: 引擎盖之下

464 阅读3分钟

原文地址:medium.com/flutter-com…

原文作者:sayanmondal342.medium.com/

发布时间:2021年5月19日

Flutter是一个移动SDK,由谷歌建立和开源;其核心是让每个人都能建立漂亮的跨平台移动应用(现在也可用于网络和桌面)。📱

无论您是来自网页开发还是原生移动开发领域,Flutter都能让您以一种熟悉的、简化的方式创建移动应用。

它是一个平台,提供了你构建全面应用所需的一切:渲染引擎、UI组件、测试框架、工具、路由,以及更多。


在这篇文章中,我们不仅要研究,还要深入了解Flutter真正的超级力量,那就是渲染,它每天都会发生超过一百万次。👨🏻💻

渲染

您的Flutter应用程序总是与一个巨大的Widget Tree🌲相连。即使是最简单的应用程序,你也会看到一个相当长的Widget Tree。在Flutter中默认提供的基本计数器应用的Widget树看起来是这样的(实际上它比这个大得多)。

image.png

Flutter小部件是反应性的。它们对来自外部的任何新信息做出反应。考虑将一个有状态的组件作为另一个无状态组件的父代。

在这种情况下,只要无状态组件所依赖的状态之一发生变化,小部件就会调用 didUpdateWidget 生命周期方法,并在必要时重新绘制。比如说。

IconButton(
    icon: Icons.add,
    onPressed: (){
        setState((){
            this.value++;
        })
    }
),
Text("Value = ${this.value}")

在这个例子中,价值状态是文本小部件的一部分,每次收到图标按钮的onPressed回调时都会更新。按钮调用setState()方法将告诉Flutter重新绘制依赖于状态变化的小部件。

Flutter知道它需要重建,因为IconButton的状态被标记为脏。

让我们以一种循序渐进的方式来看待这个问题🧗

  1. 用户点击Icon Button。
  2. 你的应用程序调用IconButton.onPressed()回调中的setState方法。
  3. Flutter意识到它需要重新构建,因为里面的状态值已经更新,它调用了didUpdateWidget,导致IconButton被标记为脏。
  4. 新的部件取代了部件树中的旧部件。
  5. Flutter渲染了新的树。

现在你知道了flutter是如何知道何时渲染一个新的widget的,让我们看看渲染是如何通过一系列的步骤发生的。

image.png

渲染管道

这是Flutter的渲染引擎在渲染对象时采取的一系列步骤。本概述将对该管道中的步骤进行高层次的描述。


动画制作

Flutter通过启动一个动画勾选器来启动渲染过程。如果一个元素需要重新绘制,例如,如果你正在向下滚动一个列表,在这样的情况下,列表的起始位置会逐步移动到其结束位置,以便它有一个平滑的过渡。

这是由动画刻度线控制的,它决定了一个元素必须移动的时间。因此,你可以控制动画的戏剧性程度。在一个动画过程中,flutter会重建并绘制每一帧。


构建

在这一步中,Flutter建立并构建了Widget Tree。在构建Widget树时,这里会考虑到Widget的个别配置,而不是Widget的形状和大小。

这意味着该Widget在屏幕中的数据和配置在这里被考虑在内,它实际上不是在构建一个蓝盒子或类似的东西。Widgets只是处理最终将被画在屏幕上的配置。


布局

在Widget组成之后,Flutter开始考虑布局。Flutter以线性时间自下而上的方式在树上行走(如果你以前做过编译器设计,你可能会很容易理解这一部分)。

当它沿着树走的时候,它收集关于小部件位置的信息,这是在上一步定义的。在Flutter中,布局和大小是由父代向子代决定的。

Widget build(BuildContext context) {
    return Container(
        child: Row(
            children: List<Widget>[
                IconButton(
                    icon: Icons.add,
                    onPressed: () {
                        setState(() {
                            this.value++;
                        });
                    }),
                Text("Qty: ${this.value}")                
            ],
        )
    );
}

这意味着当IconButton被点到ValueUpdateWidget上时(假设这个Widget的名字是ValueUpdate),价值状态被更新,新的价值比之前的价值多一个。Flutter沿着widget树走,ValueUpdateWidget告诉按钮和文本字段它们的约束。

然后,按钮将告诉代表添加图标的部件(或与父部件进一步相关的部件,在这种情况下就是按钮)它们的约束条件,然后继续沿着树走。一旦算法在叶子节点小部件上触底,那么它就知道它们的尺寸约束。

在回去的路上,他们都可以安全地在正确的位置上占用适当的空间。


绘画

在Flutter得到了小部件约束的确切概念,并且完全确定没有冲突之后,它终于可以画出所有的小部件。

注意:这些小部件并没有在屏幕上进行实际的绘制。


合并

在这一步,Flutter将实际的小部件坐标交给屏幕。现在他们知道他们将占据的确切像素。这一步被称为合成。

出于很多原因,这一步要与绘画步骤分开。例如,让我们考虑一下当你滚动浏览一个长列表时的用例。

image.png

在这种情况下,与其每次在屏幕上滚动一个新的项目时重建你的整个列表,Flutter已经有了它们的构建和绘制,可以把它们插入需要的地方。


栅格化

现在小部件已经准备好了。引擎将整个树结合成一个可渲染的视图,并告诉操作系统来显示它。这叫做栅格化,是最后一步。

image.png

如果你想了解更多关于Flutter渲染的信息,可以看看这个谷歌技术讲座。如果我漏掉了任何一点,或者你想讨论什么,请在下面留言,我会尽快跳出来。🌟

最后,感谢你能在文章中提到这么多,并对Flutter表示出兴趣。你很了不起,每天都在做出积极的改变。祝你平安。✌🏼

在Twitter上关注Flutter社区:www.twitter.com/FlutterComm


www.deepl.com 翻译