Flutter发布的时候可谓很轰动,相对于RN或PhoneGap们,它给出了另外一种跨平台方案,更像是APP版的Unity,而且使用现代的声明式UI,据说能媲美原生性能。很吸引人,所以今天特地了解了一下。
Flutter自己实现了布局和2D图形引擎,不依赖平台提供。实际体验来看,在安卓平台完全和原生性能相当,在iOS平台与原生相比还是稍稍能感受到一些不同,主要体现在滚动和动画方面。相信大家都听说过Flutter对应安卓开发意味着什么,网上有很多关于安卓的讨论。本文将以iOS开发者的视角来看待Flutter。
在iOS平台,利用高效的CoreAnimation和独立进程渲染服务来呈现内容,这是构建性能卓越的原生应用的软件基础。我比较关心性能,一个新技术的出现,如果使用户体验开了倒车,那这门新技术普及的可能就非常小了。所以我们先来看看Flutter是如何呈现内容的:
Flutter engine提供了图形服务、文件IO以及事件等核心功能。
由上图可以看出绘制管线主要发生在UI任务运行器(UI Task Runner)和GPU任务运行器(GPU Task Runner)上,这2个运行器通常分别跑在各自的线程上。
下面是官方文档的UI任务运行器解释:
- 根隔离必须告诉引擎需要渲染帧。
- 引擎将询问平台应该在下一个vsync上通知它。
- 该平台等待下一个vsync。
- 在vsync上,引擎将唤醒Dart代码并执行以下操作:
- 更新动画插值器。
- 在布局阶段重建应用程序中的widgets。
- 布置新构造的widgets并将它们绘制成立即提交给引擎的图层树。这里没有任何实际的栅格化; 只有对需要绘制的内容的描述是作为绘制阶段的一部分构建的。
- 在屏幕上构造或更新包含有关widgets的语义信息的节点树。这用于更新平台特定的辅助功能组件。
UI任务运行器主要处理图层布局相关,调用dramFrame重建窗口图层树中的所有脏元素等,这里的过程和CALayer的drawInContext非常相似。
而Skia图形库和TextLayout等发生在GPU任务运行器里,GPU任务运行器会负责一些GPU操作相关的工作,类似于iOS平台的独立渲染服务。
我们和UIKit比较,Flutter没有像UILabel那样无法在后台线程排版的问题,整体架构也是面向高性能UI而构建的,那么为什么还有很多性能差异呢。其实也不奇怪,抛开VM和原生机器码的性能差异,苹果在优化方面是精益求精的和有平台针对性的,可能永远也不会比CoreAnimation性能更好。但Flutter是为跨平台而生的,而且尚处于Bate阶段,运行时VM以及图形渲染和动画基础结构都有非常多的性能优化空间,如果开发者参与度高或者Google开挂扶持,相信改善会非常快。
我们再来看看Flutter的整体架构:
主要分为Dart的Framwork层、C++的引擎层以及平台相关的嵌入层。可见理论上只要适配嵌入层就可以让Flutter在任何系统上运行。
实际测试发现,在iOS平台实际启动时还是会先跑完整的原生应用冷启动过程,完了再去启动Flutter系统包括注册Dart VM等,还是比较耗时的,播放完开机画后会有一段时间的黑屏,我想应该可以通过原生壳来掩盖黑屏改善体验,当然也期待能优化后能让冷启动过程速度更快一些。
总结来看,还是相当看好的,对于Flutter一个全新的跨平台方案,性能问题(用户体验)解决后,其他都不是问题。(完)