观望! Flutter!! 谷哥给安卓开发的福利!!!
Flutter 是什么?
Flutter 移动应用程序 SDK 是为开发人员提供一种创建快捷、美观的应用程序的新方式,从而摆脱过去那种千篇一律的 app
例如,这位开发者,这位,或者这位,或者由第三方编辑的一系列文章和视频
与任何新系统一样,用户想知道 Flutter 有什么与众不同之处
“Flutter 有什么新的或者令人兴奋的东西吗?”
这是一个合理的问题,本文将从技术的角度回答 Flutter 有什么东西让人兴奋,而且给出它为什么让人兴奋的原因
但首先,先讲一小段历史
移动开发的简史
移动开发是一个较新的领域
开发者们开始涉足移动开发时间尚不足十年
所以移动开发的工具仍然在发展当中
OEM SDKs
苹果的 iOS SDKs 发布于 2008 年,谷歌的 Android 软件开发工具包发布于 2009 年
这两种工具包基于不同的编程语言,分别是 Objective-C 和 Java
OEM SDKs
通过这些 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 次
因此这很可能会导致性能问题
JS 代码和原生代码本身都是很快的
瓶颈经常发生在当我们视图从一边转向另一边时
未来构建高质量的应用程序时
我们必须将使用桥接的次数控制到最小。
Flutter
和 React Native 一样,Flutter 也提供响应式的视图
Flutter 采用不同的方法避免由 JavaScript 桥接器引起的性能问题
即用名为 Dart 的程序语言来编译
Dart 是用预编译的方式编译多个平台的原生代码
这允许 Flutter 直接与平台通信,而不需要通过执行上下文切换的 JavaScript 桥接器
这就会有个问题,即它是如何实现 UI 组件的?
Widgets (组件)
Widgets 是影响和控制应用程序界面的元素
组件是移动应用中最重要的部分之一
UI 表现如何
可以成就或毁掉一款 App
-
Widgets 的外观和给人的感觉是至关重要的
Widgets 需要看起来不错
包括各种屏幕的尺寸
也需要有自然的感觉 -
Widgets 必须快速执行
创建或扩展 UI 控件(实例化他们的 Widgets)
将其放在屏幕上渲染
或者(尤其是)将其动画化 -
Widgets 应该是可扩展和可定制的
开发人员希望能够添加讨人喜欢的新的 UI 组件
并自定义所有 Widgets 以匹配各种品牌的应有程序
Flutter 的系统架构包含大量赏心悦目、快速、可定制、可扩展的 Widgets
没错,Flutter 不需要使用原生系统 UI 组件或 DOM WebViews
它自带了 Widgets
Flutter 将 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 组件
new Center (
child: new Column(
children:[
new Text ('Hello, World!')),
new Icon (Icons.star, color: Colors.green)
]
)
在这段代码中,所有的组成部分都是一个 UI 组件,包括布局
Center
UI 组件将其子组件集中在其母组件内(如屏幕)
Column
UI 组件垂直排列其子组件(UI 组件列表)
该列表包含一个Text
和一个Icon
控件(具有一个颜色属性)
在 Flutter 中,居中显示和 padding 都是 widgets
主题是适用于它们子组件的 UI 控件
甚至应用程序和导航也是 widgets
Flutter 包括很多用于布局的 widgets,不仅仅含有列,还包括行、网格、列表等
Flutter 还有一个独特的布局模型
我们称之为用于滚动的“长条布局模型 (sliver layout model)”
通过使用布局进行滚动,Flutter 可以实现高级滚动,如下所示
您可以(并且应该)自己运行这些应用程序,请参阅本文末尾的参考资料部分。
sliver layout model
长条布局模型
定制设计
UI 组件是应用程序的重要部分,你可以添加新的 UI 组件,并且可以自定义现有的 UI 组件,以使其具有不同的外观或感觉
移动设计的趋势正在与几年前普遍使用的千篇一律的应用程序背离,开始走向让用户愉悦的定制设计
Flutter 配有丰富的可定制的 Android、iOS 和 Material Design 组件
实际上 Flutter 是 Material Design 中具有最高保真度之一的实现
我们使用 Flutter 的可定制特点来构建这些组件库,以匹配多个平台上的原生组件的外观和感觉
程序开发人员可以使用相似的可定制性功能进一步调整小组件以满足他们的需求
更多关于响应式视图
现有的响应式 web 视图库都引入了虚拟 DOM,DOM 代表 HTML 的文档对象模型 (Document Object Model)
JavaScript 用 DOM 提供的 API 来操纵表现为一个元素树的 HTML 文档
虚拟 DOM 是使用编程语言中的对象(在这种情况下为 JavaScript)创建的 DOM 的抽象版本
在响应式 Web 视图(由 ReactJS 和其他系统实现)中,虚拟 DOM 是不可变的,每次更改,所有的东西都得重建
系统将虚拟 DOM 与真正的 DOM 进行比较,生成一组最小的更改,然后执行这些更改,以更新真正的 DOM
最后,平台重新绘制真实的 DOM 到画布中
这听起来增加了很多额外的工作,但它是值得的,因为操纵 HTML DOM 是非常耗费系统资源的。
React Native 也做类似的工作,但是是在移动应用程序当中进行的。它会操控移动平台上的原生组件而不是 DOM。它构建一个 UI 组件的虚拟树,与原生组件进行比较,并只更新已更改的部件。
React Native 虚拟树
请记住,React Native 必须通过桥接器与原生部件进行通信,因此,UI 组件的虚拟树可以帮助保持传递桥的最小值,同时还允许使用原生部件。最后,一旦更新了本机部件,平台就会将它们渲染到画布上。
React Native 是移动开发的一大进步,并且是 Flutter 的灵感来源,但 Flutter 更进一步。
image回想一下,在 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 控件库。
兼容性
因为 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 组件