在前面的章节里我们已经使用了不少类型的widget,这一章里我们将深入理解widget的工作原理,包括以下内容:
- Widget概述
- Widget的渲染
- Flutter Inspector
- Widget的类型
- Widget的生命周期
这一章主要是一些理论上的学习,代码上的内容涉及的比较少,如果不感兴趣,可以直接跳过这一章。
什么是Widget
Widget就是用来构成UI的一个基本模块,就像乐高一样,通过把这些Widget进行组合拼装,能够形成各种复杂的界面。Flutter能够非常简单地通过Widget的各种组合来完成UI的构建,就像我们之前做的那样,而Widget就像是一个展示APP 状态的蓝图。
根据给定的状态(state),Widget将会为你构建一个对应的UI。
分析Card2
在之前的代码中我们自定义了一个Widget:Card2,现在我们来看看在这个过程中的各种细节问题吧。
这个Widget的结构分解如下:
可以看到,Card2由一下Widget组合而成:
- Container widget: 整体的容器,设置了背景图片,样式,并进行子Widget的布局.
• Column widget: 在垂直方向上排列子Widget
• AuthorCard custom widget:展示作者的头像和名字.
• Expanded widget:占满剩余的空间.
• Stack widget: 将小部件放置在彼此的上面.
• Positioned widget: 在Stack中指定Widget的位置进行布局.
Widget tree
每个Widget中都有一个build()方法,在这个方法里我们通过组合其他的Widget来构造我们需要的UI,这就像是一个树形结构一样,下图就是Card2的树形结构图:
同样,我们可以分解AuthorCard和Expanded:
Widget tree可以形象的为我们展示UI的布局结构,系统在渲染Widget的时候会遍历树的各个节点,并调用各节点的build()的方法,最终将我们需要的UI展示出来。
Widget的渲染
在第一章里,我们了解到Flutter的结构包括三层:
本章里我们将关注Framework层,我们把这一层分成四个部分:
-
Material and Cupertino 是Widget层顶部的UI控制库,它决定了我们的UI风格是Android还是IOS.。
-
Widgets层是关于Widget的抽象组合,它包含了创建UI的所有原生类. 参见官方文档: https://api.flutter.dev/flutter/widgets/widgets-library.html.
-
Rendering层是一个布局抽象,它可以绘制和处理widget的布局,这样你就不必计算每个widget的坐标和管理每一帧的绘制了。
-
Foundation层,即dart:ui 层, 包含处理动画、绘画和手势的核心库。
回到Framework层,为了完成Widget的渲染,它需要同时处理三种树:
- Widget Tree
- Element Tree
- RenderObject Tree
下图就是Widget如在这一原理下如何工作的:
- Widget: 公共 API,开发者可以用来创建自己的Widget。
- Element:管理一个小部件和一个小部件的渲染对象。对于树中的每个小部件实例,都有一个相应的元素。
- RenderObject: 负责绘制和布局一个特定的小部件实例。还可以处理用户交互,如输入,点击测试和手势。
存在两种类型的Element:
- ComponentElement:一种由其他element组合成的element,它对应组合Widget中的其他Widget。
- RenderObjectElement: 一种保存渲染对象的element。
请记住,每个element都包含一个渲染对象,以执行小部件绘制、布局和点击测试。
以Card2为例,来看看具体的工作原理:
正如你在前几章中所看到的,Flutter通过调用runApp()来运行应用程序。然后,每个widget的build()方法里又是很多widget组合而成的子widget树。对于widget树中的每个widget,Flutter将创建一个相应的element,element tree管理每个widget实例和对应的渲染对象,并告诉framework层如何来渲染这个widget。
关于Widget的渲染,可以看看以下视频讲解:
https://youtu.be/996ZgFRENMs