为何 Flutter 选择 Dart 语言

为何 Flutter 选择 Dart 语言

原文地址 https://medium.com/hackernoon/why-flutter-uses-dart-dd635a054ebf

许多语言学家认为人说的自然语言影响他们的思维方式。 相同的概念是否适用于计算机语言? 使用不同种类的编程语言工作的程序员通常会提出根本不同的问题解决方案。 举一个更极端的例子,计算机科学家消除了 goto 语句鼓励采用更有条理的程序(与novel 1984中的极权主义者的领导者不太一样,他们从自然语言中删除异端词以消除 thoughtcrimes)。

这与FlutterDart有什么关系? 早期的 Flutter 团队评估了十多种语言,并选择了 Dart,因为它与他们构建用户界面的方式匹配。

Dart 是开发人员喜欢 Flutter 的重要原因。以下是 Dart 功能的快速列表,这些功能使 Flutter 必不可少:

  • Dart 是 AOT(Ahead Of Time),已编译为快速,可预测的本机代码,几乎所有 Flutter 都可以用 Dart 编写。这不仅使 Flutter 更快,而且几乎所有内容(包括所有小部件)都可以自定义。
  • Dart 也可以通过 JIT(Just In Time)进行编译,以实现异常快速的开发周期和改变游戏规则的工作流程(包括 Flutter 流行的亚秒级有状态热重装)。
  • Dart 使创建以 60fps 运行的平滑动画和过渡更加容易。 Dart 可以在没有锁的情况下进行对象分配和垃圾回收。与 JavaScript 一样,Dart 避免了抢先式调度和共享内存(从而避免了锁定)。由于 Flutter 应用程序已编译为本机代码,因此它们不需要在领域之间建立缓慢的桥梁(例如,JavaScript 到本机)。它们的启动速度也快得多。
  • Dart 允许 Flutter 避免使用像 JSX 或 XML 这样的声明式布局语言,也不需要单独的可视界面构建器,因为 Dart 的声明式程序化布局易于阅读和可视化。而且,由于所有布局都以一种语言和一种位置显示,因此 Flutter 可以轻松地提供使布局变得轻松的高级工具。 *开发人员发现 Dart 特别易于学习,因为它具有静态和动态语言用户都熟悉的功能。

并非所有这些功能都是 Dart 独有的,但是它们的组合达到了一个“甜头”,这使 Dart 在实施 Flutter 方面具有独特的功能。如此之多,很难想象 Flutter 会像没有 Dart 一样强大。

本文的其余部分将更深入地介绍 Dart 的许多特性(包括其标准库),这些特性使其成为实现 Flutter 的最佳语言。

编译和执行

如果您已经了解静态和动态语言,AOT 和 JIT 编译以及虚拟机等主题,则可以跳过本节。

从历史上讲,计算机语言已分为两类:静态语言(例如,Fortran 或 C,其中在编译时静态键入变量)和动态语言(例如 Smalltalk 或 JavaScript,其中变量的类型可以在运行时更改)。 通常会编译静态语言以为目标机器生成本机代码(或assembly code)程序,这些程序在运行时直接由硬件执行。 动态语言由解释器执行,而不会产生机器语言代码。

当然,事情最终变得更加复杂。 虚拟机(VM)的概念变得很流行,它实际上只是一个模仿软件中的硬件机器的高级解释器。虚拟机可以更轻松地将语言移植到新的硬件平台。在这种情况下,VM 的输入语言通常是中间语言。例如,一种编程语言(例如Java)被编译为中间语言(字节码。 org / wiki / Java_bytecode)),然后在 VM(JVM)上执行。

另外,现在有Just-in-time(JIT)编译器。 JIT 编译器会在程序执行期间运行,并进行即时编译。在程序创建期间(运行时之前)执行的原始编译器现在称为ahead-of-time(AOT)编译器

通常,只有静态语言才适合将 AOT 编译为本机机器代码,因为机器语言通常需要知道数据的类型,而在动态语言中,类型不是预先固定的。 因此,通常会解释动态语言或编译 JIT。

在开发过程中完成 AOT 编译后,它总是会导致开发周期大大缩短(从对程序进行更改到能够执行程序以查看更改结果之间的时间)。 但是 AOT 编译导致程序可以更可预测地执行,而不会在运行时暂停分析和编译。 AOT 编译的程序也开始更快地执行(因为它们已经被编译)。

相反,JIT 编译可提供更快的开发周期,但会导致执行速度较慢或更加不稳定。 特别是,JIT 编译器的启动时间较慢,因为在程序开始运行时,JIT 编译器必须在执行代码之前进行分析和编译。 研究表明如果开始执行需要花费几秒钟的时间,许多人就会放弃应用程序

结合使用 AOT 和 JIT 编译的优点会很棒吗?

编译和运行 Dart

在开发 Dart 之前,Dart 团队的成员已经在高级编译器和虚拟机上进行了开创性的工作,二者均针对动态语言(例如V8 引擎和 JavaScript Strongtalk和静态语言(例如 Java 的Hotspot 编译器)。他们利用这种经验使 Dart 在如何进行编译和执行方面异常灵活。

Dart 是极少数适合于同时编译 AOT 和 JIT 的语言之一(也许是唯一的“主流”语言)。支持这两种编译为 Dart 和(尤其是 Flutter)提供了明显的优势。

在开发过程中使用 JIT 编译,使用的编译器特别快。然后,当应用程序准备发布时,将对其进行 AOT 编译。因此,借助高级工具和编译器,Dart 可以提供两全其美的优势:极快的开发周期,快速的执行和启动时间。

Dart 在编译和执行方面的灵活性不止于此。例如,可以将 Dart 编译为 JavaScript,使其可以由浏览器执行。这允许在移动应用程序和 Web 应用程序之间重复使用代码。开发人员报告的代码重用率高达 70%。 Dart 也可以在服务器上使用,方法是编译为本机代码,或者编译为 JavaScript,然后将其与node.js一起使用。

最后,Dart 还提供了一个独立的 VM,它使用 Dart 语言本身作为其中间语言(本质上就像解释器一样)。

Dart 可以有效地编译 AOT 或 JIT,解释或转换为其他语言。 Dart 的编译和执行不仅异常灵活,而且特别是fast

有状态的热加载功能

Flutter 最受欢迎的功能之一是它极速热加载功能。 在开发期间,Flutter 使用 JIT 编译器,该编译器通常可以在一秒钟内重新加载并继续执行代码。 只要有可能,应用状态就会在每次重新加载时保持不变,因此该应用可以从中断处继续运行。

除非您亲自体验过,否则很难理解真正快速(可靠)的热重装在开发过程中有多重要。 开发人员报告说,它改变了他们创建应用程序的方式,将其描述为将其应用程序栩栩如生

Flutter 的热加载功能使尝试新想法或尝试替代方法变得容易得多,极大地促进了创造力。 到目前为止,我们已经讨论了 Dart 如何使开发人员更满意。 下一节将介绍 Dart 如何使创建用户满意的流畅应用变得更加容易。

规避垃圾

快速的应用程序很棒,但平滑的应用程序更好。 即使是超级快的动画,如果看起来很生涩,也会看起来很糟糕。 但是,阻止jank可能很困难,因为有很多不同的原因。 Dart 具有许多功能,可避免造成抽搐的许多常见情况。

当然,(像任何语言一样)仍然可以在 Flutter 中编写一个简陋的应用程序。 Dart 更具可预测性,可帮助开发人员更好地控制其应用的平滑度,从而更轻松地提供最佳的用户体验,无所不能。

这里有一份测试结果

以 60 fps 的速度运行,使用 Flutter 创建的用户界面的性能远远优于使用其他跨平台开发框架创建的用户界面。

不仅比跨平台应用程序更好,而且与最佳本机应用程序一样好:

用户界面非常流畅……我从未见过如此流畅的 Android 应用程序。

AOT 编译和“桥梁”

我们已经讨论了一项有助于使事情保持平稳的功能,那就是 Dart 能够 AOT 编译为本地机器代码的功能。 预编译的 AOT 代码比 JIT 更具可预测性,因为在运行时不会暂停以执行 JIT 分析或编译。

但是,AOT 编译代码有一个更大的优势,那就是避免了“ JavaScript bridge”。 当动态语言(例如 JavaScript)需要与平台上的本机代码进行互操作时,它们必须通过bridge进行通信,这会导致上下文开关,它们必须保存特别多的状态(可能会保存到辅助状态) 存储)。 这些上下文切换是双重打击,因为它们不仅减慢了运行速度,而且可能导致严重的问题。

注意:即使编译的代码也可能需要与平台代码进行对话的接口,这也可以称为桥接,但是通常比动态语言所需的桥接要快几个数量级。 此外,由于 Dart 允许将小部件之类的内容移入应用程序,因此减少了跨过bridge的需要。

抢先式调度,时间分片和共享资源

大多数支持多个并发执行线程的计算机语言(包括 Java,Kotlin,Objective-C 和 Swift)都使用抢占在线程之间进行切换。 每个线程都分配了一个“执行时间”,如果超过了分配的时间,则使用上下文切换来抢占该线程。 但是,如果在更新线程(例如内存)之间共享的资源时发生抢占,则这会导致竞争条件

竞争状况是双重打击,因为它们可能导致严重的错误,包括使您的应用程序崩溃并导致数据丢失,而且由于依赖于独立线程的相对时间.,因此特别难以查找和修复。 在调试器中运行应用程序时,很难捕捉竞争条件

解决争用条件的典型方法是使用锁来保护共享资源,该锁可以阻止其他线程执行,但锁本身会引起垃圾,或甚至更严重的问题(包括死锁饥饿)。

Dart 针对此问题采用了不同的方法。 Dart 中称为isolates的线程不共享内存,从而避免了大多数锁的需要。隔离通过在通道上传递消息来进行通信,这与Erlang中的actors或 JavaScript 中的web worker相似。

Dart 和 JavaScript 一样,都是单线程,这意味着它根本不允许抢占。相反,线程显式地产生(使用async / await,FuturesStreams)。这使开发人员可以更好地控制执行。单线程可帮助开发人员确保关键功能(包括动画和过渡)在没有抢占的情况下得以执行。这不仅对用户界面,而且对于其他客户端-服务器代码,通常都是一个很大的优势。

当然,如果开发人员忘记放弃控制,这可能会延迟其他代码的执行。 但是,我们发现,忘记屈服通常比忘记锁定容易得多(因为很难找到竞争条件)。

分配和垃圾收集

造成垃圾的另一个严重原因是垃圾收集。 确实,这只是访问共享资源(内存)的一种特殊情况,在许多语言中,这都需要使用锁。 但是在收集可用内存时,锁定可能会阻止整个应用程序运行。 但是,Dart 几乎可以在所有时间无锁执行垃圾回收。

Dart 使用了一种高级的世代垃圾收集和分配方案,该方法对于分配许多短命的特别快 对象(对于像 Flutter 这样的反应性用户界面来说,这是完美的,它为每个帧重建了不变的视图树)。 Dart 可以使用单个指针凹凸分配对象(无需锁定)。 再次,这将导致平滑的滚动和动画效果,而不会产生混乱。

统一布局

Dart 的另一个好处是 Flutter 不会在程序与其他模板化或布局语言(例如 JSX 或 XML)之间拆分布局,也不需要单独的可视化布局工具。 这是用 Dart 编写的简单 Flutter 视图:

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

请注意,可视化此代码产生的输出是多么容易(即使您没有使用 Dart 的经验)。

请注意,由于 Flutter 使用 Dart 2,现在布局变得更加简单明了,因为关键字 new 是可选的,因此静态布局看起来更像是使用声明性布局语言编写的,如下所示:

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

但是,我知道您可能在想什么-专用布局语言的lack如何称为advantage? 但这实际上是一个改变游戏规则的人。 这就是开发人员在题为“ 为什么本机应用程序开发人员应该认真看待 Flutter”。

在 Flutter 中,仅使用 Dart 代码定义布局。 没有 XML /模板语言。 也没有视觉设计师/故事板工具。

我的直觉是,听到这个消息后,你们中的一些人甚至会有些畏缩。 表面看来,这也是我的反应。 使用视觉工具进行布局难道不是一件容易的事。 用代码编写各种约束逻辑会不会使事情变得过于复杂?

答案是“否”。 和男孩! 真是大开眼界。

答案的第一部分是上面提到的热重载。

对于 Android 的 Instant Run 或任何类似的解决方案,这比现在快了几年,我对此压力还不够。 即使在大型非平凡应用程序上,它也能正常工作。 而且快疯了。 这就是 Dart 给您的力量。

实际上,这使得可视化编辑器界面变得多余。 我一点也没有错过 XCode 相当不错的自动布局**。

Dart 可以创建简洁明了的布局,而“疯狂的快速”热重载则使您可以立即看到结果。 这包括布局的非静态部分。

因此,与 Flutter(Dart)相比,我在 Android / XCode 上的写作布局都更加高效。 一旦掌握了它(对我来说这意味着几个星期),由于几乎没有发生上下文切换,因此可以大大减少开销。 人们不必切换到设计模式,只需选择鼠标并开始单击即可。 然后想知道是否必须以编程方式完成某些事情,如何实现该目标等。一切都是编程方式。 而且 API 的设计非常好。 它很快就会变得直观,并且比自动布局/布局 XML 提供的构造功能强大得多。

例如,下面是一个简单的列表布局,该列表布局以编程方式定义的所有其他项目之间添加了分隔线(水平线):

1
2
3
4
5
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 和 AngularDart),我在本文中引用了其中的一些。

除了 Dart 本身的外部提交者之外,公共 Dart 软件包存储库中还有 3000 多个软件包,其中包括 Firebase,Redux,RxDart,国际化,加密,数据库的库 ,路由,集合等。

Dart 程序员会容易找到吗?

如果没有很多程序员知道 Dart,找到合格的程序员会更困难吗?具有讽刺意味的是,Dart 使得寻找程序员变得更加轻松,因为它是一种非常快速的学习语言。已经知道 Java,JavaScript,Kotlin,C#或 Swift 等语言的程序员几乎可以立即在 Dart 中开始编程。最重要的是,热重装鼓励用户玩 Dart 并尝试新事物,这使得学习 Dart 更快,更愉快。

这是一个程序员在标题为“ 为什么 Flutter 将于 2018 年起飞”的文章中的用法:

Dart是用于开发 Flutter 应用程序的语言,是“愚蠢易学” **。 Google 拥有创建简单,记录良好的语言(例如 Go)的经验。到目前为止,对我而言,Dart 使我想起了 Ruby,这是一种学习的乐趣。它不仅适用于移动设备,而且也适用于网络

摘自另一篇有关 Flutter 和 Dart 的文章,标题为“ 为什么 Flutter?而不是框架 X?还是更好,为什么我要全力以赴。

Flutter 也使用由 Google 创建的 Dart 语言,说实话,我不喜欢 C#或 JAVA 之类的强类型语言,但我不知道 Dart 编写代码的方式为何如此不同。我写起来很舒服。也许是因为它非常简单易学。

通过广泛的 UX 研究和测试,Dart 专门设计为熟悉且易于学习。例如,在 2017 年上半年,Flutter 团队进行了八位开发人员进行的 UX 研究 。我们向他们简要介绍了 Flutter,然后将它们松散了一个小时左右,以创建一个简单的视图。所有参与者都能够立即开始编程,即使他们以前从未使用过 Dart。他们专注于编写反应性视图,而不是语言。 Dart 刚刚工作

摘自另一篇文章有 ​​ 关 Flutter 和 Dart 的文章,标题为“ 为什么 Flutter?而不是框架 X?还是更好,为什么我要全力以赴。

Flutter 也使用由 Google 创建的 Dart 语言,说实话,我不喜欢 C#或 JAVA 之类的强类型语言,但我不知道 Dart 编码的方式为何如此不同。我写起来很舒服。也许是因为它非常简单易学。

例如,在 2017 年上半年,Flutter 团队进行了八位开发人员进行的 UX 研究。我们向他们简要介绍了 Flutter,然后将它们松散了一个小时左右,以创建一个简单的视图。所有参与者都能够立即开始他们专注于编写反应性视图,而不是语言。Dart 刚刚工作

作为直接的证据,Google 内部的一个大型项目希望将其移动应用程序移植到 iOS。 他们打算雇用一些 iOS 程序员,但决定尝试 Flutter。 他们监控了使开发人员快速掌握 Flutter 所花费的时间。 他们的结果表明,程序员可以在三周内学习 Dart 和 Flutter 并提高工作效率。 相比之下,他们之前观察到的五个星期可以使程序员仅在 Android 上就可以上手(更不用说他们必须雇用和培训 iOS 的开发人员)。

最后,文章“ [为什么我们选择 Flutter,以及它如何使我们的公司变得更好](https://medium.com/@matthew.smith_66715/why-we-chose-flutter-and-how-its-changed- “我们的公司更好的 271ddd25da60”来自一家公司,该公司将其大型企业应用程序迁移到所有三个平台(iOS,Android 和 Web)上的 Dart。 他们的结论:

更容易录用。 现在,无论来自 Web,iOS 还是 Android,我们都将寻求最佳人选。

现在,我们所有团队都被整合到一个单一的代码库中,因此带宽提高了 3 倍。

知识共享空前高涨

他们可以使用 Dart 和 Flutter 将生产力提高三倍。鉴于他们之前所做的事情,这不足为奇。与许多公司一样,他们正在使用独立的语言,工具和程序员为每个平台(Web,iOS 和 Android)构建独立的应用程序。改用 Dart 意味着他们不再需要雇用三种不同的程序员。对于他们来说,将现有的程序员转移到 Dart 上很容易。

他们和其他人发现,一旦程序员开始使用 Flutter,他们经常爱上 Dart。他们喜欢语言的简洁性和缺乏仪式感。他们喜欢语言功能,例如级联,命名参数,异步/等待和流。最重要的是,他们喜欢 Dart 所提供的 Flutter 功能(例如热重装),而 Dart 帮助他们构建的漂亮,高性能的应用程序。

Dart 2

在本文发布时,Dart 2也已发布。 Dart 2 专注于改善构建客户端应用程序的体验,包括开发人员速度,改进的开发人员工具和类型安全性。 例如,Dart 2 具有sound 类型 systemtype 推理

Dart 2 还将new关键字设为可选。 这意味着可以完全不使用任何关键字来描述许多 Flutter 视图,从而使它们不那么混乱并且更易于阅读。 例如:

1
2
3
4
5
6
7
8
Widget build(BuildContext context) =>
  Center(child:
    Column(children: [
      Text('Hello, World!'),
      Icon(Icons.star, color: Colors.green),
    ])
  )

Dart 2 还通过使用类型推断来使对 const 关键字的许多使用成为可选,因为不需要在 const 上下文内冗余地指定 const。 例如,以下语句:

1
2
3
4
const breakfast = {
   const Doughnuts(): const [const Cruller(), const BostonCream()],
};

现在可以替换为:

1
2
3
4
const breakfast = {
   Doughnuts(): [Cruller(), BostonCream()],
};

因为breakfastconst,其他所有内容也都推定为const

更加专注

Dart 2 中的改进集中在优化客户端开发上。 但是 Dart 仍然是构建服务器端,台式机,嵌入式系统或其他程序的绝佳语言。

专注是一件好事。 专注于几乎可以使所有持久的流行语言受益。 例如:

  • C 是用于编写操作系统和编译器的系统编程语言。 它变得更多了。 Java 是一种[专为嵌入式系统设计的]语言(https://en.wikipedia.org/wiki/Java_(software_platform)#History)。
  • JavaScript 是 Web 浏览器的脚本语言(!)。 *甚至备受反对的 PHP 也成功了,因为它专注于编写“个人主页”(并以此命名)。

另一方面,许多语言已经明确尝试(但失败)成为完全通用的语言,例如 PL / 1 和 Ada 等。 最普遍的问题是,在没有焦点的情况下,这些语言成了众所周知的厨房水槽。

使 Dart 成为出色的客户端语言的许多功能也使它成为服务器端使用的更好语言。 例如,Dart 避免了抢先式多任务这一事实使它具有与服务器上的 Node 相同的优势,但打字效果更好,更安全。

为嵌入式系统编写软件也是如此。 Dart 可靠地处理多个并发输入的能力是这里的关键。

最后,Dart 在客户端上的成功将不可避免地引起更多在服务器上使用它的兴趣,就像 JavaScript 和 Node 发生的情况一样。 为什么要强迫人们使用两种不同的语言来构建客户端服务器软件?

结论

这是 Dart 激动人心的时刻。 使用 Dart 的人喜欢它,Dart 2 的新功能使其成为您的工具库中更有价值的补充。 如果您没有使用 Dart,希望本文为您提供有关 Dart 的新功能或不同之处的有价值的信息,并且您可以尝试使用它和 Flutter。

Rating: