漫谈Flutter渲染

Flutter如何进行渲染

Flutter 是一个跨平台的 UI 工具集,它的设计初衷,就是允许在各种操作系统上复用同样的代码,尽可能的复用代码,达到一份代码在多个平台能够运行的目的。为了让在各个系统平台都有行为一致的显示效果,从而没有选择像React使用原生的视图空间进行绘制,Flutter自建自己的测量,布局,绘制引擎,这样就同时也避免了像Rect一样通过Bridge进行通信的效率低下的问题。如此设计是为了让开发者能够在不同的平台上,都能交付拥有原生体验的高性能应用,尽可能地共享复用代码的同时,包容不同平台的差异。Flutter之前版本使用的Skia,最新的Flutter的版本已经在IOS使用Impeller,Android版本也在适配过程中。Skia是Android和Chrome的渲染引擎,在Flutter中优化不能达到极致,所有就开发了Impeller。Android的运行时环境同样经历这个阶段,Android 4.4之前使用的是Dalvik虚拟机,之后开发性能更好的ART虚拟机。

Flutter三种树

Flutter渲染过程中有三个类,Widget,Element,RenderObject。我们一般情况下开发普通业务逻辑的应用,会用继承或者组合Widget进行开发。在Flutter绘制过程中会存在三种树桩结构,示例如下所示: 根据Widget生成Element,然后创建相应的RenderObject并关联到Element.renderObject属性上,最后再通过RenderObject来完成布局排列和绘制。

Widget树作为Flutter渲染的基石。Widget代表 UI 组件,例如按钮、文本字段和图像。这些不可变,实体封装了 UI的所需状态和配置。它们的轻量级特性使它们能够有效地描述应用的当前状态。Widgets是轻量级同时实例化成本比较低,所以Widget树能够有效地描述应用的状态。Widget轻量同时实例化成本低,这也是Flutter推荐使用嵌套,而不把padding作为一个属性的原因之一。

Element树充当不可变Widget树和可变RenderObject树之间的桥梁。每个Element都包含对Widget和RenderObject的引用。Element擅长比较两个对象,特别是Widget和RenderObject。Element本质上表示使用Widget来配置树中的特定位置。Element作为Widget和RenderObject之间的桥梁。

RenderObject树包含渲染实际Widget的逻辑。RenderObject对象更重量级,实例化成本更高。RenderObject处理布局、绘制和命中测试等任务。将渲染对象尽可能长时间保留在内存中并可能由于实例化成本高而回收它们是有益的。

总之Widigets件描述"什么"(UI 设计)。 Element负责连接和管理更新。 RenderObject处理"如何"(高效渲染)。

Flutter次线性布局

其他一些工具包使用 O(N²) 或更糟糕的布局算法(例如,约束域中的不动点迭代)。 Flutter 的目标在于布局初始化的线性性能,及一般情况下更新现有布局的次线性布局性能。Flutter的UI布局的总策略是限制从父Widget传递到子Widget,Widget的大小从子Widget传递到父Widget,父Widget最终决定子Widget的大小和位置。为了保证布局性能的高效,Flutter采取了从上到下,深度优先遍历一次的算法。如果子Widget的宽度或者高度超过父Widget的宽度或者高度,界面会直接报错(为了性能直接报错,防止多次来回测量)。该策略将可能存在的单独测量和布局传递合并为单次传递,因此,每个渲染对象在布局过程中最多被访问两次:一次在树的向下传递过程中,一次在树的向上传递过程中。这样就达到了O(N)级别的布局算法。因为是O(N)级别的高效布局算法,所以Flutter推荐使用嵌套等Widget布局方式,无惧Widget的层级。

Flutter响应式用户界面

Flutter作为一个响应式UI框架,开发灵感来源于Facebook的React。创建和更新UI元素的操作被分离开了,容易造成它们的不同步。单向数据流会成为此问题的解决方案。Flutter与其他响应式框架类似,采用了显式剥离基础状态和用户界面的方式,来解决这一问题。 widget 通过重写该方法来声明 UI 的构造:

UI = f(state)

总之

Flutter一切都是Widget的口号是围绕着通过组合Widget来构建用户界面。Widget又由更为基础的Widget 构成。这种积极组合的结果是需要精心设计的算法和数据结构才能有效处理大量的Widget。通过一些额外的机制,这些数据结构还能使开发者轻松构建无限滚动列表,以便在 widget 可见时进行按需构建。

致谢

希望文章对大家有所帮助,如果文章有所纰漏请不吝指教,大家共同进步。欢迎关注"技术蔡"的公众号,此公众号也是本作者的技术相关的公众号。

相关推荐
江上清风山间明月15 小时前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能1 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人1 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen1 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang1 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang1 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1231 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-2 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力2 天前
Flutter应用开发:对象存储管理图片
flutter