一文理解Flutter全貌

一文理解Flutter全貌

原文地址 https://medium.com/hackernoon/whats-revolutionary-about-flutter-946915b09514

Flutter 是什么

Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作。在全世界,Flutter 正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

Flutter 广受欢迎,官方 github 仓库已经有 82.1K 的 Star。 另外,大量应用采用 flutter 开发,可以参考 github 上的 awesome-flutter

到底 flutter 有和与众不同呢?我们先看看移动应用开发的发展史。

移动应用开发简史

移动应用程序开发是一个相对较新的领域。 第三方开发人员已经能够构建移动应用程序不到十年,因此工具仍在不断发展也就不足为奇了。

移动平台 SDK

Apple iOS SDK 于 2008 年发布,Google Android SDK 于 2009 年发布。这两个 SDK 分别基于不同的语言:Objective-C 和 Java。

您的应用程序与平台对话以创建小部件,或访问照相机等服务。 这些小部件将呈现到屏幕画布上,并且事件将传递回这些小部件。 这是一个简单的体系结构,但是您几乎必须为每个平台创建单独的应用程序,因为窗口小部件是不同的,更不用说本地语言了。

移动端 WebViews

第一个跨平台框架基于 JavaScript 和 WebViews。 示例包括相关框架:PhoneGap,Apache Cordova,Ionic 等。 在 Apple 发布 iOS SDK 之前,他们鼓励第三方开发人员为 iPhone 构建 Web 应用程序,因此使用 Web 技术构建跨平台应用程序飞速发展。

您的应用程序将创建 HTML 并将其显示在平台上的 WebView 中。 请注意,像 JavaScript 这样的语言很难直接与本机代码(如服务)对话,因此它们要经过一个“桥”,该桥在 JavaScript 领域和本机领域之间进行上下文切换。 因为通常不会经常调用平台服务,所以这不会引起太多性能问题。

响应式视图

ReactJSMercury 之类的响应性 Web 框架已变得流行,主要是因为它们简化了创建过程 通过使用从[响应式编程](https://en.wikipedia.org/wiki/Reactive_programming)借用的编程模式来进行网络浏览。 在 2015 年,React Native 将响应式视图的许多优点带入移动应用程序。

虽然 React Native 非常流行,但是由于 JavaScript 领域访问了原生领域中的平台小部件,它必须通过桥梁访问原生组件。 小部件通常被相当频繁地访问(在动画,过渡或用户用手指在屏幕上“滑动”某些东西时,每秒访问多达 60 次),这可能会导致性能问题。 正如这篇有关 React Native 的文章所述:

Here lies one of the main keys to understanding React Native performance. Each realm by itself is blazingly fast. The performance bottleneck often occurs when we move from one realm to the other. In order to architect performant React Native apps, we must keep passes over the bridge to a minimum.

Flutter

与 React Native 一样,Flutter 也提供了响应式视图。 Flutter 采用了另一种方法来避免由于使用已编译的编程语言 Dart 而需要 JavaScript 桥而导致的性能问题。 Dart 被“提前”(AOT)编译成适用于多个平台的本机代码。 这使 Flutter 无需通过进行上下文切换的 JavaScript 桥即可与平台进行通信。 编译为本机代码还可以缩短应用程序启动时间。

Flutter 是唯一一个无需 JavaScript 桥即可提供反应式视图的移动 SDK,这一事实足以使 Flutter 变得有趣且值得一试,但是 Flutter 有一些“革命性的”东西,这就是 Flutter 实现 widgets 的方式。

小部件

小部件是影响和控制应用程序视图和界面的元素。 毫不夸张地说,小部件是移动应用程序中最重要的部分之一。 实际上,仅小部件就可以makebreak一个应用程序。

  • 小部件的“外观”和“感觉”至关重要。 小部件必须看起来不错,包括各种屏幕尺寸。 他们还需要感到自然。
  • 窗口小部件必须“快速”执行:创建窗口小部件树,为窗口小部件充气(实例化其子对象),将其放置在屏幕上,对其进行渲染或(尤其是)对其进行动画处理。
  • 对于现代应用,小部件应“可扩展”和“可定制”。 开发人员希望能够添加令人愉悦的新小部件,并自定义所有小部件以匹配应用程序的品牌。

Flutter 具有一种新的体系结构,其中包括外观和感觉良好,快速,可自定义和可扩展的小部件。 Flutter 不使用平台小部件(或 DOM WebView),而是提供了自己的小部件。

Flutter 将小部件和渲染器从平台提升到应用程序中,从而使它们可以自定义和扩展。 Flutter 对平台的要求是在画布中渲染小部件,以便它们可以显示在设备屏幕上,并可以访问事件(触摸,计时器等)和服务(位置,摄像头等)。

Dart 程序(绿色)和本机平台代码(对于 iOS 或 Android 为蓝色)之间仍然存在接口,该接口可以进行数据编码和解码,但这可能比 JavaScript 桥快几个数量级。

将小部件和渲染器移入应用程序确实会影响应用程序的大小。 Android 上 Flutter 应用程序的最小大小约为 4.7MB,这与使用类似工具构建的最小应用程序相似。 你可以自己权衡 Flutter 的好处是否值得,因此本文的其余部分将讨论这些好处。

布局

Flutter 的最大改进之一是它如何进行布局。 布局根据一组规则(也称为约束)确定小部件的大小和位置。

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

CSS 包含许多布局模型,包括(多个)盒子模型,浮动元素,表格,多列文本,页面媒体等。后来添加了其他布局模型,例如 flexbox 和 grid,因为开发人员和设计人员需要对布局进行更多控制,并使用表格和透明图像来获得所需的内容。在传统布局中,开发人员无法添加新的布局模型,因此必须将 flexbox 和 grid 添加到 CSS 并在所有浏览器上实现。

传统布局的另一个问题是,规则可以相互交互(甚至冲突),并且元素通常会应用数十条规则。这使布局变慢。更糟糕的是,布局性能通常约为 N 平方,因此,随着元素数量的增加,布局的速度会进一步降低。

Flutter 是 Google 的 Chrome 浏览器小组成员进行的一项实验。我们想看看如果忽略传统的布局模型,是否可以构建更快的渲染器。几周后,我们取得了明显的性能提升。我们发现:

  • 大多数布局是相对简单的,例如:滚动页面上的文本,大小和位置仅取决于显示器大小的固定矩形,以及某些表格,浮动元素等。
  • 大多数布局是窗口小部件的子树的本地布局,并且该子树通常使用一种布局模型,因此这些窗口小部件仅需要支持少量规则。

我们意识到,如果将其放在头上,可以大大简化布局:

  • 每个窗口小部件都将指定自己的简单布局模型,而不是将大量布局规则应用于任何窗口小部件。
  • 因为每个小部件都需要考虑的布局规则要少得多,所以可以对布局进行重大优化。
  • 为了进一步简化布局,我们将几乎所有内容都变成了小部件。

这段Flutter代码,用于创建具有布局的简单小部件树:

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

该代码具有足够的语义,您可以轻松想象它将产生什么,但是显示结果如下:

在此代码中一切都是小部件,包括布局。 “居中”小部件将其子对象置于其父对象(例如屏幕)内部。 “列”布局小部件垂直排列其子级(小部件列表)。 该列包含一个“文本”窗口小部件和一个“图标”窗口小部件(它确实具有其颜色的属性)。

在Flutter中,居中和填充是小部件。 主题是小部件,适用于其子级。 甚至应用程序和导航也是小部件。

Flutter包括许多用于布局的小部件,不仅包括列,还包括行,网格,列表等。此外,Flutter具有一个独特的布局模型,我们称之为“条形布局模型”,用于滚动。 Flutter中的布局是如此之快,可以用于滚动。 考虑一下。 滚动必须瞬时且平滑,以使用户在将其拖到物理屏幕上时感觉像屏幕图像已附着在其手指上。

通过使用布局进行滚动,Flutter可以实现高级滚动,

在大多数情况下,Flutter可以一次完成布局,这意味着在线性时间内,因此它可以处理大量的小部件。 Flutter还可以进行缓存和其他操作,因此可以尽可能避免进行布局。

自定义设计

由于窗口小部件现在是应用程序的一部分,因此可以添加新的窗口小部件,并且可以自定义现有的窗口小部件以赋予它们不同的外观或感觉,或者与公司的品牌相匹配。 移动设计的趋势已经从几年前很普遍的千篇一律的应用程序转移到了使用户满意并赢得奖项的定制设计上。

Flutter随附了适用于Android,iOSMaterial Design的丰富,可自定义的小部件集(实际上,我们拥有 被告知Flutter具有Material Design最高保真度的实现之一。 我们使用Flutter的可定制性来构建这些小部件集,以匹配多个平台上本机小部件的外观。 应用程序开发人员可以使用相同的可定制性来进一步调整小部件,以满足其需求。

响应式视图补充说明

用于响应式Web视图的库引入了“虚拟DOM”。 DOM是HTML文档对象模型,这是JavaScript用来处理HTML文档的API,以元素树的形式表示。 虚拟DOM是使用编程语言(在本例中为JavaScript)的对象创建的DOM的抽象版本。

在反应式Web视图(由ReactJS等系统实现)中,虚拟DOM是不可变的,并且每当发生任何更改时都从头开始重建。 将虚拟DOM与真实DOM进行比较,以生成一组最小更改,然后执行这些更改以更新真实DOM。 最后,平台重新渲染真实的DOM并将其绘制到画布中。

这听起来可能需要做很多额外的工作,但这是非常值得的,因为操作HTML DOM非常昂贵

React Native的功能与此类似,但适用于移动应用程序。 它代替DOM,而是在移动平台上操纵本机窗口小部件。 它构建虚拟的窗口小部件树,而不是虚拟DOM,并将其与本机窗口小部件进行比较,仅更新已更改的树。

请记住,React Native必须通过桥与本机窗口小部件进行通信,因此,窗口小部件的虚拟树有助于将通过桥的传递保持在最低限度,同时仍允许使用本机窗口小部件。 最后,更新本机小部件后,平台会将其渲染到画布上。

React Native是移动开发的一大胜利,它是Flutter的灵感来源,但Flutter进一步迈进了一步。

回想一下,在Flutter中,小部件和渲染器已经从平台上提起,进入了用户的应用程序。没有可操作的本机平台窗口小部件,因此虚拟窗口小部件树现在是_the_小部件树。 Flutter渲染小部件树并将其绘制到平台画布上。这很好,很简单(而且很快)。另外,动画发生在用户空间中,因此应用程序(以及开发人员)对此具有更多控制权。

Flutter渲染器本身很有趣:它使用几种内部树结构来仅渲染那些需要在屏幕上更新的小部件。例如,渲染器使用“ 使用合成的结构重画”(“结构”的意思是_by小部件_,比通过屏幕上的矩形区域执行效率更高)。不变的窗口小部件,即使是已移动的窗口小部件,都可以从缓存中“ bit blitted”,这是非常快的。这是使滚动在Flutter中如此出色的原因之一,即使在高级滚动中也是如此(上面已讨论和显示)。

为了进一步了解Flutter渲染器,我推荐此视频。您还可以查看代码,因为Flutter是开放源代码。当然,您可以自定义甚至替换整个堆栈,包括渲染器,合成器,动画,手势识别器和(当然)小部件。

Dart 语言

因为Flutter(与使用反应式视图的其他系统一样)会为每个新框架刷新视图树,所以它会创建许多对象,这些对象可能只存在一帧(十分之一秒)。幸运的是,Dart使用了“ 世代垃圾收集”,因为对象(尤其是寿命短的对象)非常有效)相对便宜。此外,可以通过单个指针碰撞完成对象的分配,这是快速的并且不需要锁。这有助于避免UI jank和卡顿现象。

Dart还具有一个“ tree抖动”编译器,该编译器仅包含您应用中所需的代码。即使您只需要一个或两个小部件,也可以随意使用大的小部件库。

有关Dart的更多信息,请阅读“ 为什么Flutter使用Dart”。

热加载

Flutter最受欢迎的功能之一是快速,有状态的热装。 您可以在Flutter应用程序运行时对其进行更改,它会重新加载已更改的应用程序代码,并使其从中断的位置继续(通常不到一秒钟)。 如果您的应用遇到错误,通常可以修复该错误,然后继续进行,就好像该错误从未发生过一样。 即使您必须进行完全重装,它也很快。

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

兼容性

由于窗口小部件(以及这些窗口小部件的渲染器)是应用程序的一部分,而不是平台的一部分,因此请不要使用“ 兼容库”是必需的。您的应用不仅可以使用,而且在最新的OS版本(Android Jelly Bean和更高版本以及iOS 8.0和更高版本)上也可以使用。这大大减少了在较旧的OS版本上测试应用程序的需求。另外,您的应用可能会在将来的OS版本上运行。

我们被问到一个潜在的问题。由于Flutter不使用本机平台窗口小部件,因此,当出现支持新类型窗口小部件的新版本的iOS或Android或更改现有窗口小部件的外观或行为时,Flutter小部件将需要很长时间进行更新?

  • 首先,Google是Flutter的内部大用户,因此我们强烈希望更新小部件集,以使其保持最新状态并尽可能接近当前平台小部件。
  • 如果有时候我们更新小部件的速度太慢,那么Google并不是Flutter唯一拥有使小部件保持最新状态的用户。 Flutter的窗口小部件可扩展且可自定义,以至任何人都可以更新它们,甚至您也可以。甚至无需提交拉取请求。您将不必等待Flutter本身被更新。
  • 以上几点仅在您希望使新更改反映在您的应用中时适用。如果您不希望所做的更改影响到您应用的外观或行为方式,那就太好了。小部件是您应用程序的一部分,因此,小部件将永远不会从您的下方变出来,并且不会使您的应用程序看起来很糟糕(或更糟糕的是,破坏了您的应用程序)。
  • 另外一个好处是,您可以编写应用程序,以便即使在较旧的OS版本上也可以使用新的小部件。

其他优点

Flutter的简单性使其速度很快,但是强大的可定制性和可扩展性使它变得强大。

Dart具有软件包存储库,因此您可以扩展应用程序的功能。例如,有许多软件包可以轻松访问Firebase,以便您构建“无服务器”应用程序。外部贡献者创建了一个程序包,使您可以访问Redux数据存储。还有一些名为“ plugins”的软件包,使它们可以独立于OS的方式更轻松地访问平台服务和硬件,例如加速度计或照相机。

当然,Flutter还是开源,再加上Flutter渲染堆栈是应用程序的一部分,这意味着您可以为个人定制几乎任何想要的东西应用程式。此图中绿色的所有内容均可自定义:

如果有人问您有关Flutter的问题,那么您现在知道如何回答:

  • 反应式视图的优势,无需JavaScript桥接
  • 快速,流畅且可预测; 代码将AOT编译为本机(ARM)代码
  • 开发人员可以完全控制小部件和布局
  • 带有精美的,可自定义的小部件
  • 出色的开发人员工具,具有惊人的热重装
  • 更高性能,更多兼容性,更多乐趣

上面并未提及跨品台性,实际上,Flutter可以从一个代码库为多个平台构建美观,快速的应用程序。可定制性和可扩展性使Flutter可以轻松地面向多个平台,而不会降低性能或功能。

相关网站

相关视频:

相关应用:

Further reading:

Rating: