[关闭]
@qinyun 2017-09-19T14:44:15.000000Z 字数 7643 阅读 2723

为什么说Flutter是革命性的?

移动开发


译者按:在本文发布的时候,Flutter的SDK尚不能从中国大陆直接下载,不过我们在和本文作者沟通的时候,他表示Google正在考虑为国内开发者提供更便捷的下载方式。

Flutter是什么?

Flutter移动应用程序SDK是为开发人员提供一种创建快捷、美观的应用程序的新方式,从而摆脱过去那种千篇一律的app,尝试过Flutter的人都会真的爱上它;例如,这位开发者这位,或者这位,或者由第三方编辑的一系列文章和视频

与任何新系统一样,用户想知道Flutter有什么与众不同之处,“Flutter有什么新的或者令人兴奋的东西吗?”,这是一个合理的问题,本文将从技术的角度回答Flutter有什么东西让人兴奋,而且给出它为什么让人兴奋的原因。

但首先,先讲一小段历史。

移动开发的简史

移动开发是一个较新的领域,开发者们开始涉足移动开发时间尚不足十年,所以移动开发的工具仍然在发展当中,这并不奇怪。

OEM SDKs

苹果的iOS SDKs发布于2008年,谷歌的Android软件开发工具包发布于2009年,这两种工具包基于不同的编程语言,分别是Objective-C和Java。

通过这些SDK,你的应用可以与系统通信,以创建UI组件或访问系统相机。这些组件被渲染到手机屏幕,而相应的事件则被传回给组件。这个架构足够简单,但你仍然不得不为每个平台开发单独的App,因为这些系统组件都是不一样的,更不用提开发语言的不同了。

WebView

第一个跨平台的框架基于JavaScript 和 WebView,例如 Titanium一系列相关的框架:PhoneGap, Apache Cordova, Ionic等,在苹果发布iOS之前,他们鼓励第三方开发者为iPhone构建网页应用程序,因此使用Web技术构建跨平台应用程序是顺理成章的一步。


你的应用程序可以创建HTML并将其显示在平台的WebViews上,请注意像JavaScript这样的语言很难直接与本地代码(例如服务)进行通信,因此他们会通过一个在JavaScript代码和原生代码的“桥梁”进行上下文切换,因为平台服务通常不会经常被调用,所以这并不会导致太大的性能问题。

响应式视图

ReactJS其他的响应式编程框架已经变得很流行了,主要是因为他们通过使用从响应式编程中借用的编程模式来简化Web视图的创建过程。2015年, React Native将响应式视图的许多优势带给了移动应用程序。

React Native是非常受欢迎的(这是它应得的),但是因为JavaScript访问了原生UI组件,所以它也必须经过这些“桥接器”,界面上的UI控件通常被频繁地访问(在动画、转化或者用户用手指“滑动”屏幕上的某些东西时,每秒被访问高达60次),因此这很可能会导致性能问题。

正如关于React Native的一篇文章所说:

这是理解React Native性能的其中一个关键,JS代码和原生代码本身都是很快的,瓶颈经常发生在当我们视图从一边转向另一边时。未来构建高质量的应用程序时,我们必须将使用桥接的次数控制到最小。

Flutter

和React Native一样,Flutter也提供响应式的视图,Flutter采用不同的方法避免由JavaScript桥接器引起的性能问题,即用名为Dart的程序语言来编译。Dart是用预编译的方式编译多个平台的原生代码,这允许Flutter直接与平台通信,而不需要通过执行上下文切换的JavaScript桥接器。编译为原生代码也可以加快应用程序的启动时间。

实际上,Flutter是唯一提供响应式视图而不需要JavaScript桥接器的移动SDK,这就足以让Fluttter变得有趣而值得一试,但Flutter还有一些革命性的东西,即它是如何实现UI组件的?

组件(Widgets)

Widgets是影响和控制应用程序的视图和界面的元素,说这些组件是移动应用中最重要的部分之一,这并不夸张,事实上,UI表现如何,可以成就或毁掉一款App。

  • Widgets的外观和给人的感觉是至关重要的,Widgets需要看起来不错,包 括各种屏幕的尺寸,也需要有自然的感觉。

  • Widgets必须快速执行:创建或扩展UI控件(实例化他们的Widgets),将其放在屏幕上,渲染他们,或者(尤其是)将其动画化。

  • 对现代的应用程序来说,Widgets应该是可扩展和可定制的,开发人员希望能够添加讨人喜欢的新的UI组件,并自定义所有Widgets以匹配各种品牌的应有程序。

Flutter的系统架构包含大量赏心悦目、快速、可定制、可扩展的Widgets。没错,Flutter不需要使用系统UI组件(或DOM WebViews),它自带了Widgets。

Flutter将UI组件和渲染器从平台移动到应用程序中,这使得它们可以自定义和可扩展。Flutter唯一要求系统提供的是canvas,以便定制的UI组件可以出现在设备的屏幕上,以及访问事件(触摸,定时器等)和服务(位置、相机等)。

Dart程序(绿色)和执行数据编码和解码的原生平台代码(蓝色,适用于iOS或Android)之间仍然有一个接口,但这能比JavaScript桥接器快几个数量级。

将UI组件和渲染器移动到应用程序中确实会影响应用程序的大小。Android上的Flutter应用程序的的初始大小约为6.7M,这与类似的工具构建的最小应用程序的大小相似,您可以决定Flutter的优势是否值得权衡,因此本文的余下部分将讨论这些优势。

布局

Flutter最大的改进之一就是它的布局,布局是基于一组规则(也称约束)来决定UI组件的大小和位置。

传统上,布局使用大量可以应用于任何UI组件的规则。这些规则实现多种布局方法,我们就以众所周知的CSS布局为例(尽管Android和iOS中的布局基本相似)。CSS具有适用于HTML元素(UI组件)的属性(规则), CSS3定义了375个属性。

CSS包含大量的布局模型,如多种箱模型、浮动元素、表、多列文本、分页媒介等。还有像flexbox 和 grid的布局模型在之后也被添加进去,因为开发人员和设计人员需要对布局进行更多地控制,而不得不使用表格和透明图像来获取他们想要的布局。在传统布局中,开发人员无法添加新的布局模型,因此必须将flexbox 和 grid添加到CSS中并在所有浏览器上实现。

传统布局的另一个问题是规则可以相互影响甚至发生冲突,通常有几十种规则元素的规则应用于他们,这使得布局变慢。更糟糕的是,布局性能通常为指数性下降,因此,随着元件数量的增加,布局变慢得更快。

Flutter最开始是Google Chrome浏览器小组成员进行的实验项目,我们想看看如果我们忽略了传统的布局模式,是否可以构建更快的渲染器。几周后,我们在性能上取得了显著增长,我们发现:

  • 大多数的布局是相对简单的,例如:滚动页面上的文本,其大小和位置只取决于显示大小的固定矩形,还有一些表格,浮动元素等。
  • 大部分布局只作用于UI组件树的一部分,并且这子树通常使用一个布局模型,因此这些UI组件只需要少量的规则。

我们意识到如果完全改变以前的布局模式,布局就可以大大被简化:

  • 每个UI组件都将指定自己简单的布局模型,而不是拥有可以应用于任何UI组件的一整套布局规则。
  • 因为每个UI组件都有一个更小的一套布局需要考虑,所以布局可以大量优化。
  • 为了进一步简化布局,我们几乎将所有内容都转换为UI组件。

这里是用Flutter代码来创建的一个带有布局的简单UI组件。

  1. new Center (
  2. child: new Column(
  3. children:[
  4. new Text ('Hello, World!')),
  5. new Icon (Icons.star, color: Colors.green)
  6. ]
  7. )

这段代码在语义上足够清晰。您可以轻松地想象它将会生成什么。运行这段代码的显示结果如下:

  1. Hello, World!

在这段代码中,所有的组成部分都是一个UI组件,包括布局。 Center UI组件将其子组件集中在其母组件内(如屏幕)。ColumnUI组件垂直排列其子组件(UI组件列表)。该列表包含一个Text和一个Icon控件(具有一个颜色属性)。

在Flutter中,居中显示和padding都是widgets,主题是适用于它们子组件的UI控件,甚至应用程序和导航也是widgets。

Flutter包括很多用于布局的widgets,不仅仅含有列,还包括行、网格、列表等。 此外,Flutter还有一个独特的布局模型,我们称之为用于滚动的“长条布局模型 (sliver layout model)”。Flutter中的布局非常快,可用于滚动。试想一下,滚动必须如此快速平滑,以至于让用户感觉当他们在物理屏幕上拖动时,屏幕图像就像和他们的手指相连一样。

通过使用布局进行滚动,Flutter可以实现高级滚动,如下所示。请注意,这些是GIF动画,真正的Flutter应用程序更加平滑。您可以(并且应该)自己运行这些应用程序,请参阅本文末尾的参考资料部分。

在大多数情况下,Flutter仅需一次传递即可完成布局,这意味着布局所花的时间是线性增长的,所以它可以处理大量的widgets。Flutter也可以利用缓存或其他功能来避免重复的布局。

定制设计

因为UI组件现在是应用程序的一部分,你可以添加新的UI组件,并且可以自定义现有的UI组件,以使其具有不同的外观或感觉,或匹配公司的品牌,移动设计的趋势正在与几年前普遍使用的千篇一律的应用程序背离,开始走向让用户愉悦的定制设计。

Flutter配有丰富的可定制的Android、iOSMaterial Design组件(实际上,我们已经被告知Flutter是Material Design中具有最高保真度之一的实现),我们使用Flutter的可定制特点来构建这些组件库,以匹配多个平台上的原生组件的外观和感觉。程序开发人员可以使用相似的可定制性功能进一步调整小组件以满足他们的需求。

更多关于响应式视图

现有的响应式web视图库都引入了虚拟DOM,DOM代表HTML的文档对象模型。JavaScript用DOM提供的API来操纵表现为一个元素树的HTML文档。虚拟DOM是使用编程语言中的对象(在这种情况下为JavaScript)创建的DOM的抽象版本。

在响应式Web视图(由 ReactJS和其他系统实现)中,虚拟DOM是不可变的,每次更改,所有的东西都得重建。系统将虚拟DOM与真正的DOM进行比较,生成一组最小的更改,然后执行这些更改,以更新真正的DOM。最后,平台重新绘制真实的DOM到画布中。

这听起来增加了很多额外的工作,但它是值得的,因为操纵HTML DOM是非常耗费系统资源的

React Native 也做类似的工作,但是是在移动应用程序当中进行的。它会操控移动平台上的原生组件而不是DOM。它构建一个UI组件的虚拟树,与原生组件进行比较,并只更新已更改的部件。

请记住,React Native必须通过桥接器与原生部件进行通信,因此,UI组件的虚拟树可以帮助保持传递桥的最小值,同时还允许使用原生部件。最后,一旦更新了本机部件,平台就会将它们渲染到画布上。

React Native是移动开发的一大进步,并且是Flutter的灵感来源,但Flutter更进一步。

回想一下,在Flutter中,UI组件和渲染器已经从平台中集成到用户的应用程序中。没有系统UI组件可以操作,所以原来虚拟控件树的地方现在是真实的控件树。Flutter渲染UI控件树并将其绘制到平台画布上。这很好,既简单又快。 此外,动画发生在用户空间中,因此应用程序(因此开发人员)可以对其进行更多的控制。

Flutter渲染器本身很有趣:它使用几个内部树结构来渲染只需要在屏幕上更新的UI组件。例如,渲染器使用“ 使用合成的结构重绘”(这意味着比使用屏幕上的矩形区域更有效)。不变的UI控件,即使是那些已经移动的UI控件,仅需在内存中做极其细微的改动,速度当然超级快。这就是为什么Flutter的滚动性能如此之高,即使在很复杂的滚动场景中。

要进一步了解Flutter渲染器,我推荐这个视频。你也可以看看代码,因为Flutter是开源的。当然,您可以自定义或甚至替换整个堆栈,包括渲染器,合成器,动画,手势识别器,当然还有widgets。

Dart编程语言

因为Flutter 像使用响应式视图的其他系统一样,刷新每个新框架的视图树,它会创建许多只能在一帧(六十分之一秒)内存在的对象。幸运的是,Dart使用“generational garbage collection ”对于这样的系统来说是非常有效的,因为对象(特别是寿命短的)消耗资源相对较少。此外,可以使用单个pointer bump来完成对象的分配。这是一个快速且不需要锁定的pointer bump。这有助于避免UI 卡顿

Dart还有一个“tree shaking ”编译器,它只包含你在应用程序中需要的代码。 即使您只需要一个或两个,您也可以随意使用大型的UI控件库。

热重载

Flutter最受欢迎的功能之一是其快速,保留程序状态的热重载 (hot reload)。 您可以在Flutter应用程序运行时对其进行更改,重新加载应用程序的代码,将其从之前的操作位置继续下去。一次热重载通常用不到一秒钟。 如果您的应用遇到错误,您通常可以修复错误,然后继续,就像错误从未发生过。 即使你必须完全重新加载,它也是很快速的。

开发人员告诉我们,这可以让他们“绘制”他们的应用程序,一次更改,然后几乎立即可以看到结果,而无需重新启动应用程序。

兼容性

因为UI组件(和这些UI组件的渲染器)是您的应用程序的一部分,而不是平台的一部分,不需要“兼容库 ”。 您的应用程序不仅可以正常工作,而且在最近的操作系统版本Jelly Bean以后的安卓系统和 8.0以后的iOS系统上也是一样的 。 这显著降低了在旧版本操作系统上测试应用程序的需求。 此外,你的App有很大可能与未来的操作系统版本兼容。

我们曾被问到一个潜在的问题。由于Flutter不使用原生UI组件,因此,当新的iOS或Android版本出现时,Flutter UI组件是否需要更新才能支持新的部件,或更改现有部件的外观或行为吗?

  • 首先,Google是Flutter的内部的一个大用户,所以我们有很大的动机来更新UI组件,使其保持最新状态并尽可能接近当前的原生UI组件。

  • 如果有一段时间我们在更新一个UI组件时太慢,Google并不是Flutter唯一一个保持UI组件最新的用户。Flutter的UI组件是可扩展和可定制的,任何人都可以更新它们,包括你自己, 甚至不需要提交一个请求。 你永远不必等待Flutter自己更新。

  • 只有当您想要在应用中反映出新的更改时,上述要点才适用。 如果您不想要更改影响您的应用程序的外观或工作方式,那么就没有必要使用上面所说的。 UI组件是您的应用程序的一部分,所以UI永远不会在你不知情的情况下擅自改变,并使您的应用程序看起来不好(或更糟的是,破坏您的应用程序)。

  • 还有一个额外的好处,您可以编写您的应用程序,以便即使在较旧的操作系统版本上也能使用新的UI组件.

其他优势

Flutter的简单性使其运行很快,但它的可定制性和可扩展性,保持简单的同时拥有强大功能。

Dart拥有一个软件包仓库。您可以用这些软件包扩展应用程序的功能。 例如,有许多软件包可以轻松访问Firebase,以便您可以构建“无服务器”应用程序。 外部贡献者创建了一个可让您访问 Redux data store的软件包。 还有一些称为“ plugins ”的软件包,可以以独立于操作系统的方式轻松访问平台服务和硬件,例如加速度计或相机。

当然,Flutter也是一个开放源码的项目 ,加上Flutter渲染堆栈是您应用程序的一部分,这意味着您可以自定义几乎任何您想要的应用程序。 该图中绿色的部分您都可以定制:

那么,“Flutter有什么新鲜又令人兴奋的”呢?

如果有人问你Flutter,现在你知道如何回答他们了:

  • 响应式视图的优点,不需要JavaScript的桥接器
  • 快速,流畅,可预测; 代码将AOT编译为本机(ARM)代码
  • 开发人员完全控制UI组件和布局
  • 配有美观,可定制的UI组件
  • 强大的开发者工具,惊人的热重新加载
  • 性能更好,兼容性更好,开发起来更有乐趣

你注意到我把什么移出这个名单吗? 这是通常人们在谈论Flutter时提到的第一件事,但对我来说,这是Flutter中最不重要的事情之一。

这就是,Flutter可以从单个代码库为多个平台构建漂亮而快速的应用程序。 当然这应该列出来的! 它的可定制性和可扩展性可以轻松将Flutter定位到多个平台,而不会牺牲性能或功耗。

Flutter的革命性

我还没有完全解释为什么Flutter是“革命性”的。 这其实是一个很合适的评价,因为外部开发人员用Flutter构建的第一个主要应用程序之一是描述美国独立战争时期的《 汉密尔顿:美国音乐剧 》的官方应用程序。 《汉密尔顿》是百老汇最受欢迎的音乐剧之一。

该应用的开发团队Posse表示,他们选择了Flutter是因为他们需要在短短的三个月内构建应用程序。 他们称之为“一个革命性表演的革命性应用程序”,并说“Flutter是美观,高性能,品牌驱动的移动体验的绝佳选择”。该应用程序在Android和iOS的应用商店上都可下载,并且得到了越来越多的好评。

加入革命!

Flutter目前是Alpha版本。 我们还在增加更多的功能,并且我们有更多的优化计划。 然而,Google内部和外部的群组已经在使用它来构建任务关键型应用程序。

如果您对Flutter感兴趣, 您可以安装它,并体验随附安装 的一些示例应用程序 , 注意一定要试一下热重载。

如果您不是开发人员或只想看到某些应用程序,则可以安装使用Flutter构建的应用程序,并查看它们的外观和性能。 我推荐汉密尔顿应用程序 ,但还有其他应用程序 。 您还应该观看来自Google I / O的视频 ,他们在那里直播Flutter应用程序的编译过程。

资源

  • DartConf 2018年1月23日至24日,在加利福尼亚州,洛杉矶

网站

视频

应用

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注