Flutter 有什么优异特性和革命性创新之处?
什么是 Flutter?
Flutter mobile app SDK是一种新的方式来构建漂亮的原生移动应用程序,摆脱过去常见的“千篇一律”的应用程序。用过Flutter的人都对它赞赏有加;
相比较其他新型系统,人们想知道是什么让它与众不同,换句话说,“Flutter的创新和令人兴奋的内容到底是什么?”,这是个好问题。本文将从技术角度回答这个问题。
首先,先来讲点历史。
移动应用程序开发的简史
移动应用程序开发是一个相对较新的领域。 第三方开发人员已经能够在不到十年的时间里构建移动应用程序,所以此类工具仍在不断发展的现象并不令人觉得奇怪。
平台软件开发工具(Platform SDK)
Apple iOS SDK于2008年发布,Google Android SDK于2009年发布。这两个SDK分别基于不同的语言:Objective-C和Java。
在这个模型中,你的app通过与平台(Platform)通信以创建小部件(Widgets)或访问相机等服务。 窗口小部件会呈现在屏幕画布上(Canvas),同时事件(Event)会被传递到窗口小部件。 虽然这是一个简单的架构,但你几乎要为每个平台创建单独的应用程序,因为在不同平台上的小部件也是不同的。这样的软件开发难度可想而知更不用说还要使用原生语言开发了。
网页视图(Web view)
Web View是史上第一个跨平台框架,它基于JavaScript和WebViews,其例子包括一系列相关框架 :PhoneGap,Apache Cordova,Ionic等。 在Apple发布iOS SDK之前,Apple建议第三方开发人员使用Webapp为iPhone编写程序。因此使用Web技术构建跨平台应用程序是具有代表性的一步。
在这个框架中,你的app会创建HTML并将其显示在平台上的WebView中。 请注意,像JavaScript这样的语言很难直接与本机代码(如服务)对话,因此它们会经历一个“桥”,在JavaScript领域和本机领域之间进行上下文切换。 由于平台服务通常不会经常被调用,因此这不会导致太多性能问题。
响应视图(Reactive Views)
当下,满大街都是像ReactJS(或是其他)这样的响应式网页编程框架,主要是因为它们借鉴了响应式编程的编程模式来简化Web视图。2015年,React Native的建立给手机app上的响应式开发提供了许多便利。
React Native非常受欢迎,但是如果它想从JavaScript域中访问处于平台域(Platform)中的平台部件(Widget),它就必须通过桥接器(Bridge)。 通常,小部件需要被频繁调用(在动画,转换期间或当用户用手指“刷”屏幕上的某些内容时,调用次数被限制在了每秒最多60次),这就可能会导致性能问题。就像one article about React Native所说:
这是理解React Native性能的主要关键之一。 每个领域本身都非常快。 当我们从一个领域转移到另一个领域时,通常会出现性能瓶颈。 为了构建高性能的React Native应用程序,我们必须将桥上的数据传递保持在一定限度之内。
Flutter
与React Native一样,Flutter也提供了响应式视图。 Flutter采用不同的方法来避免因使用编译的编程语言(即Dart)而需要JavaScript桥接从而导致的性能问题。Dart是“提前”(AOT)编译为多个平台的原生代码。 它能够与Flutter与平台进直接行通信,而无需通过执行上下文切换的JavaScript桥接器。 此外,编译为原生代码的应用程序还可以缩短程序的启动时间。
事实上,Flutter是唯一的,不需要Javascript桥接的手机SDK。这足以使得它变得很有趣并值得一试。不仅如此,Flutter还有一些更具革命性的东西,比如它实现小部件的方式。
Flutter的小部件 (Widget)
窗口小部件是影响和控制应用程序视图和界面的元素。 说小部件是移动应用程序最重要的部分之一并不夸张。 事实上,单独的一个小部件就足以创建或破坏一个应用程序。
- 小部件的外观和感觉是至关重要的。 小部看起来好看,需要适配各种屏幕尺寸。同时,他们也需要感觉自然。
- 小部件必须快速执行: 创建窗口小部件树,伸缩窗口小部件(实例化他们的子窗口),将它们放在屏幕上,渲染它们,或(尤其是)为它们设置动画。
- 对于现代应用程序,窗口小部件应该是可扩展和可自定义的。开发人员希望能够添加令人愉快的新窗口小部件,并自定义与应用程序的品牌相适应的窗口小部件。
Flutter有一个新的架构,包括良好的外观,反应速度快,可定制和可扩展的小部件。 没错,Flutter不使用平台小部件(或DOM WebViews),它提供了自己的小部件。
Flutter将小部件和渲染器放到应用程序域中而不是传统的平台域中,这使小部件可以自定义和扩展。 Flutter要求平台提供画布(Canvas)(应用程序在其中呈现小部件以便它们可以出现在设备屏幕上)及访问事件(触摸,计时器等)和服务(位置,相机等)。
Dart程序(绿色)和本机平台代码(蓝色,iOS或Android)之间仍然有一个接口,可以进行数据编码和解码,但这比JavaScript桥接器快几个数量级。
事实上,将小部件和渲染器移动到应用程序中会影响应用程序的大小。 Android上Flutter应用程序的最小大小约为4.7MB,相当于使用其他工具构建的最小应用程序的大小。
本文的其余部分将讨论这些好处。
布局(Layout)
在Flutter中最大的提升之一是Layout(布局)。Layout(布局)基于一些规则(也叫约束)决定了widgets(小部件)的大小和位置。
传统上,布局使用大量能够被应用到(几乎)所有小部件的规则。这些规则被接入多种布局思路。我们以CSS布局为例,因为它很知名(尽管 安卓和iOS的布局基本上是相似的)。CSS具有的一些属性(规则)可应用于HTML元素(小部件)。CSS3定义了375个属性。
CSS包含许多布局模型,包括(多个)框模型、浮动元素、表、多列文本、分页媒体等等。后来又添加了其他的布局模型,比如flexbox和grid,因为开发人员和设计师需要对布局进行更多的控制,并使用表格和透明图像来获得他们想要的东西。在传统布局中,开发人员无法添加新的布局模型,因此必须将flexbox和grid添加到CSS中,并在所有浏览器上实现。
传统布局的另一个问题是,规则可以相互交互(甚至冲突),元素通常有许多规则应用于它们。这使得布局变慢。更糟糕的是,布局性能通常是N-的平方阶,因此随着元素数量的增加,布局会变得更慢。
Flutter最初是由谷歌的Chrome浏览器团队成员进行的一项实验。我们想看看如果我们忽略传统的布局模型,是否可以构建更快的渲染器。几周后,我们取得了显著的性能提升。我们发现:
- 大多数布局相对简单,例如:滚动页面上的文本、大小和位置仅取决于显示大小的固定矩形,以及一些表格、浮动元素等。
- 大多数布局是小部件子树的本地布局,该子树通常使用一个布局模型,因此这些小部件只需要支持少量规则。
我们意识到,如果我们把它反过来看,布局可以大大简化:
- 每个小部件将指定自己的简单布局模型,而不是一大堆可以应用于任何小部件的布局规则。•因为每个小部件需要考虑的布局规则要少得多,所以可以对布局进行大量优化。
- 为了进一步简化布局,我们几乎把所有东西都变成了一个小部件。
下面是Flutter代码,用于创建一个布局简单的小部件树:
new Center(child: new Column(children: [new Text('Hello, World!')),new Icon(Icons.star, color: Colors.green)]))
这段代码足够语义化,您可以很容易地想象它将产生什么,但是结果显示如下:
在这段代码中,一切都是一个小部件,包括布局在内。中心(Center)小部件将它的子部件放在其父部件(例如屏幕)中。列布(Column)局小部件垂直地排列其子部件(小部件列表)。该列包含一个文本(Text)小部件和一个图标(Icon)小部件(图标小部件具有属性及其颜色)。
在Flutter中,置于中心和填充的是小部件。主题是小部件,适用于它们的子组件。甚至应用程序和导航都是小部件。
Flutter 包含许多用于布局的小部件,不仅包括列,还包括行、网格、列表等。此外,Flutter还有一个独特的布局模型,我们称之为“sliver layout model”,用于滚动。Flutter中的布局非常快,可以用来滚动页面。想一下。滚动必须是即时的和平滑的,当用户在物理屏幕上拖动屏幕图像时,用户感觉屏幕图像是附着在他们的手指上的。
通过使用布局来滚动,Flutter可以实现高级类型的滚动,如下所示。注意这些都是GIF动画图像,Flutter更平滑。你可以(也应该)自己运行这些应用程序;请参阅本文末尾的参考资料部分。
Flutter Gallery appPosse Gallery appPosse Gallery app
在大多数情况下,Flutter可以一次完成布局,这意味着在线性时间内完成布局,因此它可以处理大量小部件。Flutter还可以进行缓存和其他操作,因此它可以在可能的情况下完全避免布局。
自定义设计
因为小部件现在是应用程序的一部分,所以可以添加新的小部件,并定制现有的小部件,使其具有不同的外观或感觉,或与公司的品牌相匹配。移动设计的趋势已经不再是几年前常见的千篇一律的应用程序,而是转向取悦用户并赢得奖项的定制设计。
Flutter为Android、iOS和材料设计提供了丰富的、可定制的小部件集(事实上,我们听说Flutter有着最精确的材料设计)。我们使用Flutter的可定制性来构建这些小部件集,以匹配多个平台上本机小部件的外观。应用程序开发人员可以使用相同的可定制性来进一步调整小部件以满足他们的需求。
再谈谈交互性视图
用于响应web视图的库引入了virtual DOM。DOM是HTML文档对象模型,是JavaScript用来操作HTML文档的API,表示为元素树。virtual DOM是使用编程语言(在本例中是JavaScript)中的对象创建的DOM的抽象版本。
在响应式web视图中(由诸如ReactJS等系统实现),virtual DOM是不可变的,每次发生变化都要从头开始重建。
将virtual DOM与实际DOM进行比较,以生成一组最小的更改,然后执行这些更改来更新实际DOM。
最后,平台重新呈现真实的DOM并将其绘制到画布中。
这听起来可能需要大量额外的工作,但这是非常值得的,因为操作HTML DOM非常代价非常高昂。
React Native也做了类似的事情,不过是针对移动应用。它在移动平台上操作本地小部件,而不是DOM。它不是一个虚拟DOM,而是构建一个小部件的虚拟树,并将其与本机小部件进行比较,只更新那些已经更改的小部件。
请记住,React Native必须通过桥与本机小部件进行通信,因此虚拟小部件树有助于将桥上的传递保持在最低限度,同时仍然允许使用本机小部件。最后,一旦本地小部件被更新,平台就会将它们呈现给画布。
React Native是移动开发的一大胜利,也是Flutter的灵感来源,但Flutter更进一步。
回想一下,在Flutter中,小部件和渲染器已经从平台提升到用户的应用程序中。由于没有本地平台小部件可操作,所以原来的虚拟小部件树现在变成了小部件树。Flutter呈现小部件树并将其绘制到平台画布。这很好,很简单(而且很快)。此外,动画发生在用户空间中,因此应用程序(以及开发人员)对它有更多的控制。
Flutter渲染器本身很有趣:它使用几个内部树结构只渲染那些需要在屏幕上更新的小部件。例如,渲染器使用“使用合成的结构重绘”(“结构”的意思是通过小部件,这比通过屏幕上的矩形区域更有效)。未更改的小部件,即使是那些已经移动的小部件,也会从缓存中进行“位传输(bit blit)”,这非常快。这是使滚动在抖动中表现得如此出色的原因之一,即使是在高级滚动中(如上所述)。
Dart 编程语言
因为Flutter与其他使用响应视图的系统一样, 为每个新帧刷新视图树,它创建了许多仅存活一帧(六十分之一秒)的对象。并且,Dart使用对于这类系统非常有效的“分代垃圾收集技术”,因为这样做可以降低回收对象(特别是短命的对象)的消耗。此外,Dart仅使用单个指针的增减便能完成对象的分配,这种指针运作很快并且不需要锁定。这有助于避免UI丢帧和卡顿。
Dart还有一个“ tree shaking ”编译器,它只包含你的应用程序所需的代码。您可以放心地使用大型小部件库,即使您只会用到库中的一个或两个小部件。有关Dart的更多信息,请阅读“ 为什么Flutter使用Dart ”。
实时重载
Flutter最受欢迎的原因之一就是其快速且有状态显示的实时重新加载功能。您可以在一个Flutter应用程序运行时对其进行更改,它将重新加载已更改的应用程序代码,并让它从停止的地方继续运行,通常在不到一秒钟的时间内。如果您的应用程序遇到错误,您通常可以修复错误,然后继续,就像错误从未发生过一样。即使你必须做一个完全重新加载,它依旧是很快的。
开发者们告诉我们这让他们“画”出他们自己的应用程序,做出一个改动并几乎实时看到结果却不用重新启动应用程序。
兼容性
因为小部件(包括用于小部件的渲染器)是应用程序的一部分,而不是平台的一部分,所以无需“适配链接库(Compact libraries)”。 您的应用不仅能运行,而且能在最近的系统版本上正常运行(安卓4.1及IOS 8.0)。这大大减少了在旧操作系统版本上测试应用程序的需求。此外,您的应用程序很可能适用于未来的操作系统版本。
有一个潜在的问题是,因为Flutter不使用原生平台的小部件,所以当支持新小部件的新版iOS或安卓发布时,或是当老版本的小部件的外观和行为方式被改变时,Flutter小部件是否需要很长时间才能更新?
- 首先,Google是Flutter的一个重要内部用户,因此我们有足够的热情来更新小部件集以使其保持最新状态并尽可能接近当前新平台的小部件。
- 就算窗口小部件迟迟不更新,Flutter的小部件具有很强的可扩展和可定制能力,任何人都可以更新它们,即使是你。于是,人们甚至不必提交请求,您也不必等待Flutter本身更新。
- 以上几点仅适用于当您希望在应用中使用新的小部件时。如果您不希望更改影响应用的外观或行为方式,同样也是可以的。窗口小部件是您应用的一部分,因此窗口小部件永远不会在您不知情的情况下更改并使您的应用看起来很糟糕(或者更糟糕的是,导致应用无法运行)。
- 此外,您可以通过自行编写小部件,以便即使在较旧的OS版本上也可以使用新的小部件。
其他优点
Flutter的简单性使它变得更快,同时它具有普遍的可定制性和可扩展性,使其功能强大。
Dart有一个软件包存储库,因此您可以扩展应用程序的功能。例如,有许多软件包可以轻松访问Firebase,因此您可以构建“无服务器”应用程序。外部贡献者创建了一个包,允许您访问Redux数据存储。还有一些称为“ plugins(插件)”的软件包,可以以独立于操作系统的方式,更轻松地访问平台服务和硬件,例如 加速度计或摄像头。
当然,Flutter也是开源的,再加上Flutter渲染堆栈是你应用程序的一部分,这意味着你可以为个人应用程序自定义几乎任何你想要的东西。此图中的所有绿色都可以自定义:
所以,Flutter到底新在哪,为何如此吸引人
如果有人像这样问你,现在你知道该如何回答它们了:
- 响应式视图的优点,不用JavaScript的桥接
- 快速,流畅,可预测; 代码将AOT编译为本机(ARM)代码
- 开发人员可以完全控制小部件和布局
- 配有漂亮的可定制小部件
- 出色的开发工具,具有惊人的实时重载功能
- 性能更高,兼容性更强,更有趣
你注意到我遗漏了什么吗?其实那是人们在谈论Flutter时首先提到的东西,但对我而言,这是Flutter最无趣的事情之一。
事实上,Flutter可以从单个代码库为多个平台构建漂亮而快速的应用程序。当然,它本身就是为此而生的!它的可定制性和可扩展性,可以轻松地将Flutter定位到多个平台,而不会放弃性能或功耗。
革命性
我也从未完全解释为什么Flutter是“革命性的”。但这样解释起来很合适,因为外部开发人员使用Flutter构建的第一个主要应用程序之一是“ 汉密尔顿:美国音乐剧 ” 的官方应用程序,它发生在美国独立战争时期。汉密尔顿是有史以来最受欢迎的百老汇音乐剧之一。
项目经理Posse表示,他们选择了Flutter,因为他们需要“ 在短短的三个月内 ” 构建应用程序。他们称之为“为革命性的演出创建革命性的应用”,并称“Flutter是美丽,高性能,品牌驱动的移动体验的绝佳选择。” 他们还在 Google Developer Days会议上就他们构建Flutter的应用程序的体验发表了讲话。该应用程序可在Android和iOS上使用,并获得好评如潮。
一起投身变革吧
2018年12月4日,Flutter 1.0发布。2021年3月4日,Flutter 2.0 发布,Google 将继续为其添加更多功能,并且计划进行更多优化。Flutter的使用已经开始,全球有超过250,000名开发人员。Flutter目前在Github上活跃的软件存储库中排名前20位。
如果您对Flutter感兴趣,可以安装它并使用安装附带的一些示例应用程序。一定要查看有状态显示的实时重载。
如果您不是开发人员或只是想看一些应用程序,您可以安装使用Flutter构建的应用程序,并查看它们的外观和性能。我推荐Hamilton应用程序,但还有其他优秀的程序。或者您还可以观看来自Google I / O的视频。
资源
- 观看来自Google I / O 2018的Flutter视频
- 观看2018年 1月23日至24日在加利福尼亚州洛杉矶举行的DartConf 2018的视频
- 介绍Flutter的视频。
网站:
- The Flutter website
- The source repositories (pull requests welcome!)
- More helpful links
- Gitter channel
视频:
- Experience building the Hamilton app, at GDD
- Live coding a Flutter app, at Google I/O
- Live coding with a designer, at Google I/O
- “Flutter, a new hope” at Droidcon Italy
- “The Flutter rendering pipeline”
应用:
- The app for Hamilton: An American Musical
- Flutter Gallery: for Android, on Github (also included in the flutter install at examples/flutter_gallery)
- Posse Gallery
- Friendlychat: first codelab, Firebase codelab, on Github
进一步阅读:
- 为什么Flutter使用Dart
- 向您的公司或客户推销Flutter