Flutter 选择 Dart 有什么好处?
Flutter 和 Dart 是什么关系?这实际上是非常相关的。早期的 Flutter 团队评估了不下十几种语言,最终选择了 Dart,因为它最适合如何构建用户界面。
Dart 是许多开发者喜爱 Flutter 的一个重要原因。正如这条推文所说:
这里是 Dart 功能的快速概述,这些功能共同使 Dart 对 Flutter 至关重要。
- Dart 支持 AOT(提前)编译以生成快速且可预测的机器代码。这使得几乎所有的 Flutter 组件都可以使用 Dart 来实现。这不仅可以加快 Flutter 的速度,还可以使几乎所有内容(包括所有小部件)都可自定义。
- Dart 还支持 JIT(Just In Time)编译,这大大加快了开发过程,甚至可以创建令人困惑的工作流程(包括 Flutter 流行的亚秒级热更新)。
- Dart 可以轻松编写每秒 60 帧流畅运行的动画。 Dart 能够在不加锁的情况下进行对象内存分配和垃圾回收。就像 Javascript 一样,Dart 避免了抢占式任务调度和内存共享(因此也避免了锁定)。由于 Flutter 应用程序被编译为机器代码,因此它们不需要低效的桥梁来在不同域之间进行通信(例如,原生的 Javascript)。
- Dart 使 Flutter 不再需要单独的声明性布局语言(例如 JSX 或 XML),也不需要单独的可视化界面构建器,因为 Dart 的声明性可编程布局更易于阅读和显示。而且由于所有布局都是用相同语言在同一位置编写的,Flutter 可以轻松提供用于创建布局的高级工具。
- 开发人员还发现 Dart 特别容易学习,因为它包含动态和静态语言用户都熟悉的功能。
并非所有这些功能都是 Dart 所独有的,但功能组合所引发的奇妙化学反应使 Dart 在 Flutter 实现中成为独特而强大的存在。以至于很难想象如果没有 Dart,Flutter 还能如此强大。
本文的其余部分将更详细地介绍使 Dart 成为实现 Flutter 的最佳语言(包括其标准库)的功能。
编译与执行
(如果您熟悉静态语言/动态语言、AOT/JIT编译、虚拟机等,可以跳过本节。)
纵观历史,计算机语言都有被分为两类:静态语言(例如 Fortran 或 C,变量在编译时固定为静态类型)和动态语言(例如 Smalltalk 或 Javascript,变量类型可以在运行时更改)。静态语言通常被编译成目标模型的机器代码或汇编代码,以便硬件在运行时直接执行它们。动态语言通常需要解释器来执行并且不生成机器代码。
当然,正如你所看到的,事情最终变得更加复杂。虚拟机(VM)的概念已经变得流行,但它实际上只是一个通过软件模拟硬件机器的高级解释器。虚拟机可以轻松地将语言移植到不同的硬件平台。在这种情况下,虚拟机的输入语言通常是中间语言。例如,编程语言(Java)被翻译成中间语言(字节码),然后由虚拟机(JVM)执行。
此外,当今还存在即时 (JIT) 翻译器。 JIT编译器在执行过程中编译并执行程序。因此,在执行之前翻译生成的程序的原始编译器现在称为前瞻性(AOT)编译器。
一般情况下,只有静态语言适合AOT翻译来生成机器代码,因为机器语言通常需要知道数据的类型,而动态语言的类型在运行前并不固定。因此,动态语言通常采用解释型或JIT编译型。
AOT 翻译通常会导致开发阶段的开发效率较低(需要很长时间修改代码,直到程序可以执行才能看到结果)。然而,AOT 编译生成的程序运行更可预测,并且不需要暂停执行来进行运行时分析和编译。使用 AOT 翻译生成的程序启动速度也更快(因为它们已经编译过)。
相比之下,JIT 翻译提供了更高的开发效率,但导致执行速度相对较慢且不稳定。特别是,JIT 编译的程序启动速度更慢,因为 JIT 编译器必须解析和编译代码,然后程序才能运行。许多研究表明,如果应用程序需要几秒钟才能启动,用户更有可能放弃它。
好了,这就是所有的背景信息。如果我们能够结合 AOT 和 JIT 编译的优点,那不是很好吗?请继续阅读。
编译和执行Dart
在开发Dart之前,Dart团队的成员在高级编译器和虚拟机方面做了开创性工作,包括Javascript的V8引擎和Smalltalk的Strongtalk()等动态语言和静态语言。例如 Java Hotspot 编译器)。他们利用这一经验,使 Dart 在编译和执行方面异常灵活和灵活。
Dart 是少数几个同时适合 AOT 和 JIT 翻译的语言之一(也许是唯一的“主流”语言)。这也是Dart,尤其是Flutter的一个非常重要的优势。
在开发阶段使用JIT构建以获得极快的开发体验。当应用程序准备好发布时,将通过 AOT 进行编译。同时,借助先进的工具和编译器,Dart 实现了两全其美:极快的开发效率,以及快速的启动和执行。
Dart 在翻译和执行方面的灵活性是无穷无尽的。例如,Dart 可以编译成 Javascript,以便浏览器可以运行它。这使得代码可以在移动和 Web 应用程序之间重用。开发人员报告称,他们可以在移动和 Web 应用程序之间重用高达 70% 的代码。 Dart 还可以在服务器端使用,并且可以转换为机器代码以供执行,或转换为 Javascript 以在 Node.js 中运行。
最后,Dart 还提供了一个独立的虚拟机,它本身将 Dart 作为中间代码执行(本质上就像一个解释器)。
Dart 可以使用 AOT 或 JIT 进行高效翻译,可以解释执行,也可以翻译成其他语言。不仅如此,它的编译和运行速度也很快。
状态热更新
Flutter 最受欢迎的功能之一是极快的新鲜更新。在开发阶段,Flutter使用JIT编译,可以在1秒内更新并恢复代码执行。如果可能的话,应用程序的状态会被保留,因此即使在更新后应用程序也会保留其原始状态。
如果你没有亲身经历过,很难理解快速(且可靠)的热更新对于开发有多么重要。一些开发人员报告说,它改变了他们创建应用程序的方式,就好像它给他们的应用程序带来了生命一样。
这是一位开发者对Flutter热更新的评价:
我想测试热更新,所以我改变了颜色并保存了更改,然后......我爱上了❤️。
这个功能真是令人印象深刻。我认为 Visual Studio Edit and Continue 非常好,但这只是令人震惊。我认为这是移动开发人员使生产力加倍的唯一方法。
这真的改变了我的一切。当我之前安装代码时,它会花费很长时间,而且我会失去对其他事情的关注。当我将注意力转回模拟器或设备时,我已经忘记了我需要测试什么。还有什么比浪费 5 分钟尝试将控制器调整为 2 像素更令人沮丧的呢?有了 Flutter,这一切都成为过去。
Flutter 的热门更新让您可以更快、更轻松地尝试新想法或尝试替代方案,从而极大地提升创造力。
到目前为止,我们已经讨论了 Dart 对开发人员的友好程度。让我们讨论一下 Dart 如何轻松开发流畅且用户友好的应用程序。
避免紧张
应用程序运行速度快当然好,但如果能流畅运行就更好了。如果动画很紧张,无论多快,都是不好的。然而,避免震颤很困难,因为震颤的发生原因有多种。飞镖有几个特点可以避免这些常见的振动原因。
当然,和其他语言一样,你也可以使用体验较差的 Flutter 来编写应用程序。 Dart 使开发结果更加可预测,并使开发人员能够更好地控制编写流畅的应用程序,从而比以往更轻松地实现最佳用户体验。
结论是什么?
相比其他跨平台开发框架,Flutter 在 60fps 渲染方面的表现要好很多。
不仅比其他跨平台框架更好,甚至比本机应用程序更好。
UI 是如此流畅...我从未见过如此流畅的 Android 应用程序。
AOT 翻译和“桥梁”
我们已经讨论过一个可以帮助应用程序变得更加流畅的功能,那就是 Dart 可以通过 AOT 翻译成机器代码。预编译的 AOT 代码比 JIT 更可预测,因为不需要在运行时暂停执行来进行解析和编译。
更重要的是,AOT 翻译的代码有一个巨大的优势,那就是避免了“Javascript 桥”。当动态语言(例如Javascript)需要与平台的本机代码交互时,它必须通过桥进行通信,从而导致上下文切换,并存储大量状态数据(可能在辅助存储中)。这些上下文切换对性能来说是双重打击。它们不仅减慢应用速度,还会引起强烈振动。 " data-src="https://blog-1258648987.cos.ap-shanghai.myqcloud.com/blog/why-flutter-uses-dart/1__fK1BtH5V-kO828lPg-Ukw.png" height="20" data-width="800" data-height="600" />
提醒:即使是编译后的代码也必须与平台代码进行某种程度的交互,这可以称为桥梁。但这通常比动态语言所需的要好Bridge 的速度要快很多,可以说是一个数量级的差别,另外 Dart 允许在应用程序中封装 Widgets 这样的东西,所以对 Bridges 的依赖更少。多线程并行执行(包括 Java、Kotlin、 Objective-C, and Swift) 使用抢占式多任务在线程之间切换,每个线程都有一个时隙。执行时,如果执行超过指定时间,就会被其他线程抢占。但是,如果共享资源(比如内存) 在预取发生时更新,它会导致竞争条件。
竞争条件也是双重打击,因为它们可能导致严重错误,包括应用程序崩溃和数据丢失,而且这些错误也很难重现和修复,因为它们依赖于独立线程的相对强度。执行时间处理时间。当您在调试模式下运行应用程序时,竞争问题不会出现是很常见的。
解决竞争问题的典型方法是通过锁阻止其他线程运行以保护共享资源。但锁本身可能会导致跳动甚至其他更严重的问题(包括死锁和饥饿)。
Dart 以不同的方式处理这个问题。 Dart的线程被称为isolate,并且没有共享内存,这避免了大多数锁的使用。 Isolat 通过通道传输信息,通道就像 Erlang 中的 Actor 或 Javascript 中的 Web Worker。
Dart 与 Javascript 一样,在单线程中运行。这意味着它根本不允许抢占式多任务处理。相反,线程显式放弃控制(使用 async/await、Future 或 Stream)。这使开发人员可以更好地控制执行过程。单线程可帮助开发人员确保重要功能(包括动画和过渡)可以完全执行,而不会抢占它们。这不仅对于用户界面开发而且对于其他客户端-服务器代码来说都是一个巨大的优势。
当然,如果开发人员忘记传递控制权,就会阻塞其他代码的执行。然而,我们发现忘记控制比忘记锁定更容易找到和修复(因为比赛很难找到)。
内存分配和垃圾收集
严重问题的另一个来源是垃圾收集。其实这只是很多语言中通过锁机制访问共享资源(内存)的另一种特殊形式。因为整个应用程序可能会因为内存回收过程中的锁定而崩溃。不同之处在于 Dart 几乎总是可以在没有锁的情况下进行垃圾收集。
Dart 使用先进的生成垃圾收集和内存分配机制,可以非常快地处理许多短期对象内存分配(特别适合像 Flutter 这样的敏感 UI,它每次都会构建不可变的视图树)。 Dart 可以通过碰撞单个指针来释放对象(不需要锁定)。这再次导致平滑的滚动和动画,没有抖动。
统一布局
使用 Dart 和 Flutter 的另一个好处是,您不需要将布局与程序分离,无论是模板还是其他布局语言(如 JSX 或 XML),还是单独的布局。视觉布局工具。以下是用 Dart 编写的简单 Flutter 视图:
new Center(child:
new Column(children: [
new Text('Hello, World!'),
new Icon(Icons.star, color: Colors.green),
])
)
复制代码
即使你没有使用过 Dart,也可以通过代码直观地可视化布局的效果。
需要强调的是,现在Flutter使用Dart 2,new
关键字已成为可选,使布局更简单、更清晰。上面的静态布局代码可以写得更像是声明性布局语言,例如:
Center(child:
Column(children: [
Text('Hello, World!'),
Icon(Icons.star, color: Colors.green),
])
)
复制代码
但是,我知道您想知道 - 为什么缺乏专用布局语言可以被称为优势?但这是一个非常大的变化。一位开发者在《为什么原生应用开发者应该认真对待 Flutter》一文中:
在 Flutter 中,布局是用 Dart 编写的,没有别的。没有 XML/模板语言,没有可视化设计工具/脚本工具。
我有一种感觉,当你们听到这个时,很多人都会有点畏缩。这也是我的第一反应。使用可视化布局工具不是更容易吗?编写所有布局约束逻辑会不会太复杂?
上述问题我得到的最终答案:不会。你知道,这只是大开眼界。
答案的第一部分就是前面提到的热更新。
我怎么强调都不为过,这比 Android Instant Run 或其他类似解决方案领先数光年。即使在大型应用程序中,它也能很好地工作。而且非常非常快。这就是 Dart 为您提供的。
实际上,这使得可视化编辑器变得多余。
Dart 创建简洁且易于理解的布局,然后您可以通过“令人难以置信的快速”快速更新立即看到结果。这包括布局的动态部分。我一点也不怀念 XCode 非常好的自动布局功能。
结果是,使用 Flutter(Dart)之后我的布局效率比使用 Android/XCode 之前更高。由于不需要频繁改变上下文,因此思维负担显着减轻。因为大脑不再需要切换到计划模式,拿起鼠标,单击,然后开始思考是否应该以编程方式解决某些问题或如何解决。一切都在 Flutter 中以编程方式组织。而且API的设计也相当不错。这种布局方法很快变得直观,并且比自动布局或 XML 布局提供的构造函数强大得多。
例如,以下代码展示了如何以编程方式为每隔一个列表项添加分隔线(水平线):
return new ListView.builder(itemBuilder: (context, i) {
if (i.isOdd) return new Divider();
// rest of function
});
复制代码
Flutter 中的所有布局都是在一起的,无论是静态布局还是包含程序逻辑的布局。通过使用一些新的 Dart 工具,包括 Flutter Inspector 和大纲视图(充分利用所有组合的布局),可以更轻松地创建复杂且美观的布局。
Dart 是受保护的语言吗?
不,Dart(和Flutter一样)是完全开源的,有纯开源的协议,也是ECMA标准。 Dart 在 Google 内部和外部都很受欢迎。它是 Google 内部增长最快的语言,被 Adwords、Flutter、Fuchsia 等产品使用;此外,Dart 存储库还有 100 多个外部代码贡献者。
Dart 开放性的另一个好迹象是 Google 之外的 Dart 社区的发展。例如,您可以在来自第三方(包括 Flutter 和 AngularFlutter)的 Dart 相关文章和视频中看到它非常稳定,我在本文中引用了其中的一些内容。
除了向 Dart 本身提交代码之外,外部社区参与者也在积极开发 Dart 包。目前公共 Dart 包存储库中有超过 3000 个包,涵盖 Firebase、Redux、RxDart、国际化、加密、数据库、路由、数据收集等。
招募 Dart 程序员容易吗?
如果懂Dart的程序员不多,会不会很难招到熟练的Dart程序员?相反,Dart 使招聘程序员变得很容易,因为它是一种非常容易快速学习的语言。已经了解某些语言(例如 Java、Javascript、Kotlin、C# 或 Swift)的程序员几乎可以立即开始开发 Dart。此外,最近的更新鼓励程序员享受 Dart 的乐趣并尝试新事物,使学习 Dart 变得更快、更愉快。
一位程序员在他的文章《Flutter 为什么会在 2018 年起飞》中:
Dart 作为开发 Flutter 应用程序的语言,简单易学,但有点愚蠢。 Google 拥有创建简单、文档齐全的语言(例如 Go)的经验。到目前为止,Dart 让我想起了 Ruby,学习起来真的很有趣。而且这不仅限于移动开发,也适用于Web开发。
另一篇题为《为什么选择 Flutter?而不是 X 框架?更具体地说,为什么我全身心投入 Flutter》的文章写道:
Flutter 使用的 Dart 语言也是由 Google 创建的。坦率地说。我不喜欢 C# 或 Java 等强类型语言,但我不知道为什么在 Dart 中编写代码的方式看起来不同。我觉得用 Dart 编写代码非常舒服。也许是因为它很容易学,所以很简单。
通过广泛的用户体验研究和测试,Dart 有意设计成让人感觉熟悉且易于学习。例如,2017年上半年,Flutter团队对8名开发者进行了用户体验研究。我们向他们简要介绍了 Flutter,然后给了他们一个小时的自由玩耍或创建简单视图的时间。所有参与者都可以立即开始编程,即使他们以前从未使用过 Dart。他们可以专注于编写响应式视图而不是语言。飞镖真是太神奇了。
在实验结束时,其中一位参与者(完成任务最快的)没有提及任何有关该语言的内容,因此我们询问他们是否知道自己使用的是哪种语言。他们不知道。语言并不重要;他们可以在几分钟内开始使用 Dart 进行编程。
学习一个新系统的困难不是语言本身,而是围绕该语言编写良好代码的库、框架、工具、模式和最佳实践。 Dart 的库和工具非常易于使用,并且拥有精美且完整的文档。一篇文章将其描述为:“作为额外的好处,他们非常关心代码库,并且拥有我所见过的最好的文档。”这使得学习 Dart 变得容易,并节省您可以用来学习其他内容的额外时间。
作为直接证明,Google 的一个大项目想要将其应用程序移植到 iOS。他们想雇用 iOS 程序员,但最终决定尝试 Flutter。他们研究了开发人员需要多长时间才能精通 Flutter。他们的结果是,程序员可以在三周内熟练掌握 Dart 和 Flutter 开发。相比之下,曾经有人观察到,一名程序员需要 5 周的时间来学习 Android 开发(更不用说招聘和培训 iOS 开发人员了)。
最后,文章“为什么我们选择 Flutter 以及它如何让我们的公司变得更好”提到他们在三个平台(iOS、Android 和 Web)上运行他们的企业应用程序。全部迁移到 Dart。他们的结论是:
更容易招募。我们现在只雇用最优秀的候选人,无论他们来自网络、iOS 还是 Android。
我们现在的开发能力是原来的三倍,因为我们所有的团队都团结在同一个代码库中。
知识共享从未如此有效。
使用Dart和Flutter后,他们的生产力可以提高两倍。考虑到他们之前所做的事情,这并不奇怪。与许多其他公司一样,他们使用不同的语言、工具和程序员为三个平台(Web、iOS 和 Android)开发三个独立的应用程序。通过切换到 Dart,他们不再需要雇用三种不同类型的程序员。将现有应用程序迁移到 Dart 相当容易。
他们和其他公司发现,一旦程序员开始使用 Flutter,他们就会爱上 Dart。他们喜欢语言的简单性和没有陈词滥调。他们喜欢该语言的功能,例如级联调用、命名参数、异步/等待和流。此外,他们还喜欢 Flutter 的一些功能,例如只有 Dart 才可能进行的热更新,以及帮助他们构建这些功能的漂亮而强大的 Dart 应用程序。
Dart 2
随着本文的发布,Dart 2 也随之发布。 Dart 2 致力于改善创建客户端应用程序的体验,包括开发速度、改进的开发人员工具、类型安全等等。例如,Dart 2 实现了完整的类型系统和类型推断。
Dart 2 还使 new
关键字成为可选。这意味着Flutter视图可以在没有关键字的情况下编写,使得视图代码更加简洁和可读。如下所示:
Widget build(BuildContext context) =>
Center(child:
Column(children: [
Text('Hello, World!'),
Icon(Icons.star, color: Colors.green),
])
)
复制代码
Dart 2 使用类型推断,使得 const
关键字的使用在很多地方都是可选的。在 const
上下文中,关键字 const
变得多余。例如,以下语句:
const breakfast = {
const Doughnuts(): const [const Cruller(), const BostonCream()],
};
复制代码
现在可以替换为:
const breakfast = {
Doughnuts(): [Cruller(), BostonCream()],
};
复制代码
because Dart 2 专注于优化客户端开发的体验。然而,Dart 将继续成为创建服务器端、桌面端、嵌入式系统和其他应用程序的优秀语言。 对焦很好。几乎所有长期流行的语言都受益于焦点。例如: 另一方面,有许多语言显然尝试(并失败)成为现成语言,例如 PL/1 和 Ada。他们最大的问题是缺乏专注,这导致他们成为众所周知的厨房水槽。 Dart 的许多功能使其非常适合客户端开发,也使其成为服务器端开发的良好语言。例如,避免抢占式多任务处理,Dart 具有与 Node 相同的服务器端开发优势,但具有更好、更安全的类型。 嵌入式系统的开发也是如此。至关重要的是,Dart 可以同时处理多个输入。 Dart 在客户端的成功最终将不可避免地引起人们对服务器端使用的更多兴趣,就像 Javascript 和 Node.js 一样。为什么开发人员在构建客户端-服务器软件时被迫使用两种不同的语言? 对于 Dart 来说,这是激动人心的时刻。使用过 Dart 的人都喜欢它,而 Dart 2 的新功能使其更值得您拥有它。如果您以前没有使用过 Dart,我希望本文为您提供了有关 Dart 的新颖性和不同之处的宝贵信息,并希望您能尝试使用 Flutter。 作者:chaosflutter早餐
const
const,所以其他一切❙ const 。
专注是秘诀
结论
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。