mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 06:03:45 +08:00
mod
This commit is contained in:
210
极客时间专栏/Flutter核心技术与实战/课前必读/01 | 预习篇 · 从0开始搭建Flutter工程环境.md
Normal file
210
极客时间专栏/Flutter核心技术与实战/课前必读/01 | 预习篇 · 从0开始搭建Flutter工程环境.md
Normal file
@@ -0,0 +1,210 @@
|
||||
<audio id="audio" title="01 | 预习篇 · 从0开始搭建Flutter工程环境" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/26/b8/26e053bd1920b27e46a6d63cfbcaa4b8.mp3"></audio>
|
||||
|
||||
你好,我是陈航。
|
||||
|
||||
俗话说,工欲善其事,必先利其器。任何一门新技术、新语言的学习,都需要从最基础的工程环境搭建开始,学习Flutter也不例外。所以,作为专栏的第一篇文章,我会与你逐一介绍Flutter的开发环境配置,并通过一个Demo为你演示Flutter项目是如何运行在Andorid和iOS的模拟器和真机上的。如果你已经掌握了这部分内容,那可以跳过这篇预习文章,直接开始后面内容的学习。
|
||||
|
||||
由于是跨平台开发,所以为了方便调试,你需要一个可以支持Android和iOS运行的操作系统,也就是macOS,因此后面的内容主要针对的是在macOS系统下如何配置Flutter开发环境。
|
||||
|
||||
如果你身边没有macOS系统的电脑也没关系,在Windows或Linux系统上配置Flutter也是类似的方法,一些关键的区别我也会重点说明。但这样的话,你就只能在Android单平台上开发调试了。
|
||||
|
||||
## 准备工作
|
||||
|
||||
### 安装Android Studio
|
||||
|
||||
Android Studio是基于IntelliJ IDEA的、Google官方的Android应用集成开发环境(IDE)。
|
||||
|
||||
我们在[官网](https://developer.android.com/studio/index.html?hl=zh-cn)上找到最新版(截止至本文定稿,最新版为3.4),下载后启动安装文件,剩下的就是按照系统提示进行SDK的安装和工程配置工作了。
|
||||
|
||||
配置完成后,我们打开AVD Manager,点击“Create Virtual Device”按钮创建一台Nexus 6P模拟器,至此Android Studio的安装配置工作就完成了。
|
||||
|
||||
### 安装Xcode
|
||||
|
||||
Xcode是苹果公司官方的iOS和macOS应用集成开发环境(IDE)。它的安装方式非常简单,直接在macOS系统的App Store搜索Xcode,然后安装即可。
|
||||
|
||||
安装完成后,我们会在Launchpad看到Xcode图标,打开它,按照提示接受Xcode许可协议,以及安装配置组件就可以了。
|
||||
|
||||
配置完成后,我们打开Terminal,输入命令**open -a Simulator**打开iOS模拟器,检查 **Hardware>Device** 菜单项中的设置,并试着在不同的模拟器之间做切换。
|
||||
|
||||
至此,Xcode的安装配置工作也就顺利完成了。
|
||||
|
||||
## 安装Flutter
|
||||
|
||||
Flutter源站在国内可能不太稳定,因此谷歌中国开发者社区(GDG)专门搭建了临时镜像,使得我们的Flutter 命令行工具可以到该镜像站点下载所需资源。
|
||||
|
||||
接下来,我们需要配置镜像站点的环境变量。对于macOS和Linux系统来说,我们通过文本编辑器,打开~/.bash_profile文件,在文件最后添加以下代码,来配置镜像站点的环境变量:
|
||||
|
||||
```
|
||||
export PUB_HOSTED_URL=https://pub.flutter-io.cn
|
||||
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
|
||||
|
||||
```
|
||||
|
||||
而对于Windows系统来说,我们右键点击计算机图标,依次选择属性–>高级系统设置–>高级–>环境变量,新建用户变量PUB_HOSTED_URL,其值为`https://pub.flutter-io.cn`;随后新建FLUTTER_STORAGE_BASE_URL,其值为`https://storage.flutter-io.cn`,重启电脑即可完成配置。
|
||||
|
||||
**到这里,我们就完成了镜像的配置。**
|
||||
|
||||
不过,由于GDG并不是官方组织,因此Flutter团队也无法保证此服务长期可用。但是,你也不用担心,可以关注Flutter社区 [Using Flutter in China](https://flutter.dev/community/china),来获取其他可用的镜像资源,随时更新环境变量即可。
|
||||
|
||||
随后,我们再去[Flutter官网](https://flutter.dev/docs/development/tools/sdk/releases?tab=macos),选择并下载最新的稳定版(截止至本文定稿,最新稳定版为1.5)。
|
||||
|
||||
接下来,我们把下载的压缩包解压到你想安装的目录,比如~/Documents或C:\src\flutter。为了可以在命令行中执行flutter命令,我们同样需要配置环境变量。
|
||||
|
||||
对于macOS与Linux系统,我们编辑~/.bash_profile文件,把以下代码添加至文件最后,将flutter命令的执行路径追加到环境变量PATH中:
|
||||
|
||||
```
|
||||
export PATH=~/Documents/flutter/bin:$PATH
|
||||
|
||||
```
|
||||
|
||||
而对于Windows系统,我们在当前用户变量下Path,以; 为分隔符,在其后追加flutter命令行的全路径C:\src\flutter\bin,重启电脑即可完成配置。
|
||||
|
||||
**到这里,我们就完成了Flutter SDK的安装。**
|
||||
|
||||
打开Flutter根目录,我们可以发现有一个examples文件夹,里面是一些基本的flutter示例。在今天这篇文章中,我会以hello_world示例为例,和你演示一下**如何在模拟器和真机中运行Flutter项目**。
|
||||
|
||||
**首先**,我给你介绍的是通过Flutter命令行运行的模式。进入hello_world目录,输入**flutter emulators**命令,查看当前可用的模拟器:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8b/80/8bdd7f71fce9b6053cd84b94ea01cd80.png" alt="">
|
||||
|
||||
可以看到,我们刚刚创建的两台模拟器,也就是Nexus 6P和iOS模拟器都已经在列表中了。于是,我们启动iOS模拟器,运行Flutter项目:
|
||||
|
||||
```
|
||||
flutter emulators --launch apple_ios_simulator
|
||||
flutter run
|
||||
|
||||
```
|
||||
|
||||
等待10秒左右,一个熟悉的hello world大屏幕就出现在我们面前了:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f5/74/f52718865a9025bc76f838e0fd953674.png" alt="">
|
||||
|
||||
Android模拟器的启动和运行,也与之类似,我就不再赘述了。
|
||||
|
||||
不过,使用命令行的方式来开发调试Flutter还是非常不方便,**更高效的方式是配置Android和iOS的集成开发环境**。
|
||||
|
||||
Flutter 提供了一个命令**flutter doctor**协助我们安装 Flutter的工程依赖,它会检查本地是否有Android和iOS的开发环境,如果检测到依赖缺失,就会给出对应依赖的安装方法。
|
||||
|
||||
接下来,我们试着运行下flutter doctor这条命令,得到了如下图所示的结果:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4d/24/4d9c09601bba1af3edf1bb8c4454b624.png" alt="">
|
||||
|
||||
可以看到,flutter doctor检测出了iOS工具链、Android Studio工程这两项配置中的问题。此外,由于我的电脑还安装了IDEA和VS Code,而它们也是Flutter官方支持的IDE,因此也一并检测出了问题。
|
||||
|
||||
接下来,我们根据运行flutter doctor命令得到的提示,来分别解决iOS工具链和Android Studio工程配置问题。
|
||||
|
||||
### iOS工具链设置
|
||||
|
||||
现在,我们已经可以在iOS模拟器上开发调试Flutter应用了。但要将Flutter应用部署到真实的iOS设备上,我们还需要安装一些额外的连接控制命令工具(就像通过电脑的iTunes给手机安装应用一样),并申请一个iOS开发者账号进行Xcode签名配置。
|
||||
|
||||
依据提示,我们**首先**安装libimobiledevice和ideviceinstaller这两项依赖:
|
||||
|
||||
```
|
||||
brew update
|
||||
brew install --HEAD usbmuxd
|
||||
brew link usbmuxd
|
||||
brew install --HEAD libimobiledevice
|
||||
brew install ideviceinstaller
|
||||
|
||||
```
|
||||
|
||||
其中,usbmuxd是一个与iOS设备建立多路通信连接的socket守护进程,通过它,可以将USB通信抽象为TCP通信;libimobiledevice是一个与iOS设备进行通信的跨平台协议库;而ideviceinstaller则是一个使用它们在iOS设备上管理App的工具。
|
||||
|
||||
现在,你不了解它们的具体作用也没关系,只要知道安装了它们,Flutter就可以进行iOS真机的开发调试就可以了。
|
||||
|
||||
**然后**,进行Xcode签名配置。
|
||||
|
||||
打开hello_world项目中的ios/Runner.xcworkspace,在Xcode中,选择导航面板左侧最上方的Runner项目。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/74/c8/74aed90a2891957ae084649dfba7bfc8.png" alt="">
|
||||
|
||||
在**General > Signing > Team** 中,我们需要配置一下开发团队,也就是用你的Apple ID登录Xcode。当配置完成时,Xcode会自动创建并下载开发证书。
|
||||
|
||||
任意Apple ID都支持开发和测试,但如果想将应用发布到App Store,则必须加入Apple开发者计划。开发者计划的详细信息,你可以通过苹果官方的[compare memberships](https://developer.apple.com/support/compare-memberships/)了解,这里我就不再展开了。
|
||||
|
||||
**最后**,当我们第一次连接真机设备进行开发时,Xcode会在你的帐户中自动注册这个设备,随后自动创建和下载配置文件。我们只需要在真机设备上,按照手机提示,信任你的Mac和开发证书就可以了。
|
||||
|
||||
至此,我们就可以在iOS真机上开发调试Flutter项目了。
|
||||
|
||||
### Android 工具链配置
|
||||
|
||||
相对于iOS工具链的设置,Android工具链配置就简单多了,这是因为Google官方已经在Android Studio中提供了Flutter和Dart这两个插件。因此,我们可以通过这两个工程插件,进行Flutter项目的管理以及开发调试。又因为Flutter插件本身依赖于Dart插件,所以我们只安装Flutter插件就可以了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/b7/9c/b72d5ae8fe201b230840da465e623a9c.png" alt="">
|
||||
|
||||
启动Android Studio,打开菜单项 **Preferences > Plugins**,搜索Flutter插件并点击 install进行安装。安装完毕后重启Android Studio,Flutter插件就生效了。
|
||||
|
||||
由于Android Studio本身是基于IDEA开发的,因此IDEA的环境配置与Android Studio并无不同,这里就不再赘述了。
|
||||
|
||||
对于VS Code,我们点击View->Command Palette,输入"install",然后选择"Extensions:Install Extension"。在搜索框中输入flutter,选择安装即可。
|
||||
|
||||
至此,Android的工具链配置也完成了。
|
||||
|
||||
尽管Android Studio是Google官方的Android集成开发环境,但借助于Flutter插件的支持,Android Studio也因此具备了提供一整套Flutter开发、测试、集成打包等跨平台开发环境的能力,而插件底层通过调用Xcode提供的命令行工具,可以同时支持开发调试及部署iOS和Android应用。
|
||||
|
||||
因此,**我后续的分享都会以Android Studio作为讲解Flutter开发测试的IDE。**
|
||||
|
||||
### 运行Flutter项目
|
||||
|
||||
用Android Studio打开hello_world工程(Open an existing Android Studio Project),然后定位到工具栏:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/28/f6/2832d573adb4914cfbc9195fb1a387f6.png" alt="">
|
||||
|
||||
在Target selector中,我们可以选择一个运行该应用的设备。如果没有列出可用设备,你可以采用下面的两种方式:
|
||||
|
||||
- 参考我在前面讲到的方法,也就是打开AVD Manager并创建一台Android模拟器;或是通过open -a Simulator 命令,在不同的iOS模拟器之间进行切换。
|
||||
- 直接插入Android或iOS真机。
|
||||
|
||||
hello_world工程稍微有点特殊,因为它提供了两个Dart启动入口:一个英文版的hello world-main.dart,和一个阿拉伯语版的hello world-arabic.dart。因此,我们可以在Config selector中进行启动入口的选择,也可以直接使用默认的main.dart。
|
||||
|
||||
在工具栏中点击 Run图标,稍等10秒钟左右,就可以在模拟器或真机上看到启动的应用程序了。
|
||||
|
||||
对于Flutter开发测试,如果每次修改代码都需要重新编译加载的话,那需要等待少则数十秒多则几分钟的时间才能查看样式效果,无疑是非常低效的。
|
||||
|
||||
正是因为Flutter在开发阶段使用了JIT编译模式,使得通过热重载(Hot Reload)这样的技术去进一步提升调试效率成为可能。简单来说,热重载就是在无需重新编译代码、重启应用程序、丢失程序执行状态的情况下,就能实时加载修改后的代码,查看改动效果。
|
||||
|
||||
>
|
||||
备注:我会在“02 | 预习篇 · Dart语言概览”中,与你分析Flutter使用Dart语言,同时支持AOT和JIT。
|
||||
|
||||
|
||||
就hello_world示例而言,为了体验热重载,我们还需要对代码做一些改造,将其根节点修改为StatelessWidget:
|
||||
|
||||
```
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class MyAPP extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Center(child: Text('Hello World', textDirection: TextDirection.ltr));
|
||||
}
|
||||
}
|
||||
|
||||
void main() => runApp(new MyAPP());
|
||||
|
||||
```
|
||||
|
||||
点击Run图标,然后试着修改一下代码,保存后仅需几百毫秒就可以看到最新的显示效果。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fd/79/fd4f94b6e419710103bc7a4c4750ca79.gif" alt="">
|
||||
|
||||
是不是很Cool!但是,**热重载也有一定的局限性,并不是所有的代码改动都可以通过热重载来更新。**
|
||||
|
||||
对hello_world示例而言,由于Flutter并不会在热重载后重新执行main函数,而只会根据原来的根节点重新创建控件树,因此我们刚才做了一些改造之后才支持热重载。
|
||||
|
||||
关于Flutter热重载的原理以及限制原因,我会在后面“34 | Hot Reload是怎么做到的?”文章,和你详细分析。现在,你只需要知道,如果热重载不起作用的时候,我们也不需要进行漫长的重新编译加载等待,只要点击位于工程面板左下角的热重启(Hot Restart)按钮就可以以秒级的速度进行代码重编译以及程序重启了,而它与热重载的区别只是因为重启丢失了当前程序的运行状态而已,对实际调试也没什么影响。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/30/11/307833013a128a4da31f391edebadc11.png" alt="">
|
||||
|
||||
## 总结
|
||||
|
||||
通过今天的内容,相信你已经完成了Flutter开发测试环境的安装配置,对如何在安装过程中随时检测工程依赖,以及如何分别在Android和iOS真机及模拟器上运行Flutter程序有了一定的理解,并对Flutter开发调试常用工具有了初步的认知。
|
||||
|
||||
善用这些集成工具能够帮助我们能提升Flutter开发效率,而这些有关工程环境的基础知识则为Flutter的学习提供了支撑。这样,如果你后续在开发测试中遇到了环境相关的问题,也就知道应该如何去解决。
|
||||
|
||||
## 思考题
|
||||
|
||||
你在搭建Flutter工程环境的过程中,遇到过哪些问题,又是怎么解决的呢?
|
||||
|
||||
欢迎留言告诉我,我们一起讨论。感谢你的收听,也欢迎你把这篇文章分享给更多的朋友一起阅读。
|
||||
|
||||
|
||||
129
极客时间专栏/Flutter核心技术与实战/课前必读/02 | 预习篇 · Dart语言概览.md
Normal file
129
极客时间专栏/Flutter核心技术与实战/课前必读/02 | 预习篇 · Dart语言概览.md
Normal file
@@ -0,0 +1,129 @@
|
||||
<audio id="audio" title="02 | 预习篇 · Dart语言概览" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c5/4b/c5af3a002b26151713a9e27127e3554b.mp3"></audio>
|
||||
|
||||
你好,我是陈航。
|
||||
|
||||
我们知道,Flutter开发框架采用的开发语言是Dart,所以要用好这个框架,我们必须要搞清楚Dart语言。
|
||||
|
||||
关于新技术的学习,一直以来我都非常认同一个观点:千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样才能从高维度理解问题。所以,为了帮助你更高效地掌握Dart,以最快的速度具备开发一款Flutter应用的能力,今天这篇文章,我会先从Flutter开发的角度,和你介绍Dart语言出现的历史背景、特性以及未来。
|
||||
|
||||
然后,我会在本专栏的“Dart基础”模块,与你详细分享它的特性、基础语法、类型变量、函数等知识,并和你分享一个使用Dart的综合案例,帮你学懂、学会这门语言。
|
||||
|
||||
如果你已经对Dart有一个初步印象了,也可以跳过这篇预习文章,直接学习后面的内容。
|
||||
|
||||
## Dart是什么?
|
||||
|
||||
2011年10月,在丹麦召开的GOTO大会上,Google发布了一种新的编程语言Dart。如同Kotlin和Swift的出现,分别是为了解决Java和Objective-C在编写应用程序的一些实际问题一样,Dart的诞生正是要解决JavaScript存在的、在语言本质上无法改进的缺陷。
|
||||
|
||||
那么,**JavaScript到底有哪些问题和缺陷呢?**JavaScript之父布兰登 · 艾克(Brendan Eich)曾在一次采访中说,JavaScript“几天就设计出来了”。
|
||||
|
||||
概括来说,他的设计思路是这样的:
|
||||
|
||||
- 借鉴C语言的基本语法;
|
||||
- 借鉴Java语言的数据类型和内存管理机制;
|
||||
- 借鉴Scheme语言,将函数提升到“第一等公民”(first class)的地位;
|
||||
- 借鉴Self语言,使用基于原型(prototype)的继承机制。
|
||||
|
||||
所以,**JavaScript实际上是两类编程语言风格的混合产物:(简化的)函数式编程风格,与(简化的)面向对象编程风格。**
|
||||
|
||||
由于设计时间太短,一些细节考虑得不够严谨,导致后来很长一段时间,使用JavaScript开发的程序混乱不堪。出于对JavaScript的不满,Google的程序员们决定自己写一个新语言来换掉它,所以Dart的最初定位也是一种运行在浏览器中的脚本语言。
|
||||
|
||||
而为了推广Dart,Google甚至将自己的Chrome浏览器内置了Dart VM,可以直接高效地运行Dart代码。而对于普通浏览器来说,Google也提供了一套能够将Dart代码编译成JavaScript代码的转换工具。这样一来,开发者们就可以毫无顾虑地使用Dart去开发了,而不必担心兼容问题。再加上出身名门,Dart在一开始就赢得了部分前端开发者的关注。
|
||||
|
||||
但,JavaScript的生命力似乎比预想的更强大。
|
||||
|
||||
原本JavaScript只能在浏览器中运行,但Node.js的出现让它开始有能力运行在服务端,很快手机应用与桌面应用也成为了JavaScript的宿主容器,一些明星项目比如React、React Native、Vue、Electron、NW(node-webkit)等框架如雨后春笋般崛起,迅速扩展了它的边界。
|
||||
|
||||
于是,JavaScript成为了前后端通吃的全栈语言,前端的开发模式也因此而改变,进入了一个新的世界。就如同Atwood定律描述的:凡是能用JavaScript写出来的系统,最终都会用JavaScript写出来(Any application that can be written in JavaScript, will eventually be written in JavaScript.)。
|
||||
|
||||
JavaScript因为Node.js焕发了第二春,而Dart就没有那么好的运气了。由于缺少顶级项目的使用,Dart始终不温不火。2015年,在听取了大量开发者的反馈后,Google决定将内置的Dart VM引擎从Chrome移除,这对Dart的发展来说是重大挫折,替代JavaScript就更无从谈起了。
|
||||
|
||||
但,Dart也借此机会开始转型:在Google内部孵化了移动开发框架Flutter,弯道超车进入了移动开发的领域;而在Google未来的操作系统Fuchsia中,Dart更是被指定为官方的开发语言。
|
||||
|
||||
与此同时,Dart的老本行,浏览器前端的发展也并未停滞。著名的前端框架Angular,除了常见的TS版本外,也在持续迭代对应的Dart版本[AngularDart](https://github.com/dart-lang/angular)。(不过不得不说的是,这个项目的star一直以来只有可怜的1,100出头)。
|
||||
|
||||
也正是因为使用者不多、历史包袱少,所以在经历了这么多的故事后,Dart可以彻底转变思路,成为专注大前端与跨平台生态的语言。
|
||||
|
||||
接下来,我们就从Flutter开发的视角,聊聊Dart最重要的核心特性吧。
|
||||
|
||||
## Dart的特性
|
||||
|
||||
每门语言都有各自的特点,适合自己的才是最好的。
|
||||
|
||||
作为移动端开发的后来者,Dart语言可以说是集百家之长,拥有其他优秀编程语言的诸多特性和影子,所以对于其他语言的开发者而言,学习成本无疑是非常低的。同时,Dart拥有的特点则恰到好处,在对Flutter的支持上做到了独一无二。所以,Dart成了Flutter的选择。
|
||||
|
||||
下面,我就和你详细分享下它的核心特性。
|
||||
|
||||
### JIT与AOT
|
||||
|
||||
借助于先进的工具链和编译器,Dart是少数同时支持JIT(Just In Time,即时编译)和AOT(Ahead of Time,运行前编译)的语言之一。那,到底什么是JIT和AOT呢?
|
||||
|
||||
语言在运行之前通常都需要编译,JIT和AOT则是最常见的两种编译模式。
|
||||
|
||||
- JIT在运行时即时编译,在开发周期中使用,可以动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会因为运行时即时编译受到影响。
|
||||
- AOT即提前编译,可以生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都需要提前编译,开发测试效率低。
|
||||
|
||||
总结来讲,在开发期使用JIT编译,可以缩短产品的开发周期。Flutter最受欢迎的功能之一热重载,正是基于此特性。而在发布期使用AOT,就不需要像React Native那样在跨平台JavaScript代码和原生Android、iOS代码之间建立低效的方法调用映射关系。所以说,Dart具有运行速度快、执行性能好的特点。
|
||||
|
||||
那么,**如何区分一门语言究竟是AOT还是JIT呢?**通常来说,看代码在执行前是否需要编译即可。如果需要编译,通常属于AOT;如果不需要,则属于JIT。
|
||||
|
||||
AOT的典型代表是C/C++,它们必须在执行前编译成机器码;而JIT的代表,则包括了如JavaScript、Python等几乎所有的脚本语言。
|
||||
|
||||
### 内存分配与垃圾回收
|
||||
|
||||
Dart VM的内存分配策略比较简单,创建对象时只需要在堆上移动指针,内存增长始终是线性的,省去了查找可用内存的过程。
|
||||
|
||||
在Dart中,并发是通过Isolate实现的。Isolate是类似于线程但不共享内存,独立运行的worker。这样的机制,就可以让Dart实现无锁的快速分配。
|
||||
|
||||
Dart的垃圾回收,则是采用了多生代算法。新生代在回收内存时采用“半空间”机制,触发垃圾回收时,Dart会将当前半空间中的“活跃”对象拷贝到备用空间,然后整体释放当前空间的所有内存。回收过程中,Dart只需要操作少量的“活跃”对象,没有引用的大量“死亡”对象则被忽略,这样的回收机制很适合Flutter框架中大量Widget销毁重建的场景。
|
||||
|
||||
### 单线程模型
|
||||
|
||||
支持并发执行线程的高级语言(比如,C++、Java、Objective-C),大都以抢占式的方式切换线程,即:每个线程都会被分配一个固定的时间片来执行,超过了时间片后线程上下文将被抢占后切换。如果这时正在更新线程间的共享资源,抢占后就可能导致数据不同步的问题。
|
||||
|
||||
解决这一问题的典型方法是,使用锁来保护共享资源,但锁本身又可能会带来性能损耗,甚至出现死锁等更严重的问题。
|
||||
|
||||
这时,Dart是单线程模型的优势就体现出来了,因为它天然不存在资源竞争和状态同步的问题。这就意味着,一旦某个函数开始执行,就将执行到这个函数结束,而不会被其他Dart代码打断。
|
||||
|
||||
所以,**Dart中并没有线程,只有Isolate(隔离区)**。Isolates之间不会共享内存,就像几个运行在不同进程中的worker,通过事件循环(Event Looper)在事件队列(Event Queue)上传递消息通信。
|
||||
|
||||
### 无需单独的声明式布局语言
|
||||
|
||||
在Flutter中,界面布局直接通过Dart编码来定义。
|
||||
|
||||
Dart声明式编程布局易于阅读和可视化,使得Flutter并不需要类似JSX或XML的声明式布局语言。所有的布局都使用同一种格式,也使得Flutter很容易提供高级工具使布局更简单。
|
||||
|
||||
开发过程也不需要可视化界面构建器,因为热重载可以让我们立即在手机上看到运行效果。
|
||||
|
||||
## Dart的未来
|
||||
|
||||
那么,在这样的背景下诞生的Dart,今后发展会怎样呢?
|
||||
|
||||
Dart是一个优秀而年轻的现代语言,但一种编程语言并不是搞定了引擎和开发者接口就算完成了,而是必须在这个语言得以立足的库、框架、 应用程序等“生态”都成熟起来之后,其价值才会真正开始体现。而要走到这一步,通常需要花上数年的时间。
|
||||
|
||||
目前,基于Dart语言的第三方库还很少,并且质量一般,不过值得庆幸的是,因为Flutter和Fuchsia的推动,Dart SDK更新迭代的速度快了很多,开发者的热情也急剧增长,Dart生态增速很快。
|
||||
|
||||
毕竟,在Dart社区目前最顶级的产品就是Flutter和Fuchsia了,因此Dart开发者主要以Flutter开发者居多,当然了也有用Dart开发浏览器前端的开发者,但人数并不多。所以,**我觉得Dart是否能够成功,目前来看主要取决于Flutter和Fuchsia能否成功**。**而,Flutter是构建Fuchsia的UI开发框架,因此这个问题也变成了Flutter能否成功。**
|
||||
|
||||
正如我在开篇词中提到的,Flutter正式版发布也就半年多的时间,在GitHub上Star就已经超过了68,000,仅落后React Native 10,000左右,可见热度之高。
|
||||
|
||||
现在,我们一起回到Flutter自身来看,它的出现提供了一套彻底的跨平台方案,也确实弥补了当今跨平台开发框架的短板,解决了业界痛点,极有可能成为跨平台开发领域的终极解决方案,前途光明,未来非常值得期待。
|
||||
|
||||
至此,我们已经可以清晰地看到,Google在遭受与Oracle的Java侵权案后,痛定思痛后下定决心要发展自己的语言生态的布局愿景:Dart凭借Flutter与Fuchsia的生态主攻前端和移动端,而服务端,则有借助于Docker的火热势头增长迅猛的Go语言。
|
||||
|
||||
所以说,Google的布局不仅全面,应用和影响也非常广泛,前后端均有杀手级产品用来构建语言生态。相信随着Google新系统Fuchsia的发布,Flutter和Dart会以更迅猛的速度释放它们的力量,而Google统一前后端开发技能栈的愿望也会在一定程度上得以实现。
|
||||
|
||||
## 总结
|
||||
|
||||
今天,我带你了解了Dart出现的历史背景,从Flutter开发者的视角详细介绍了Dart语言的各种特性,并分析了Dart的未来发展。
|
||||
|
||||
Dart是一门现代语言,集合了各种优秀语言的优点。如果你不了解Dart也无需担心,只要你有过其他编程语言,尤其是Java、JavaScript、Swift或Objective-C编程经验的话,可以很容易地在Dart身上找它们的影子,以极低的成本快速上手。
|
||||
|
||||
希望通过这篇文章,你可以先对Dart语言有个初步了解,为我们接下来的学习打好基础。在本专栏的“Dart基础”模块中,我会对照着其他编程语言的特性,和你讲述Dart与它们相似的设计理念,帮助你快速建立起构建Flutter程序的所需要的Dart知识体系。
|
||||
|
||||
## 思考题
|
||||
|
||||
对于学习Dart或是其他编程语言,你有什么困扰或者心得吗?
|
||||
|
||||
欢迎你在评论区给我留言分享你的经历和观点,我会在下一篇文章中等你!感谢你的收听,也欢迎你把这篇文章分享给更多的朋友一起阅读。
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<audio id="audio" title="开篇词 | 为什么每一位大前端从业者都应该学习Flutter?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/36/dd/36cec6b17deb340c1254dcf34bebcfdd.mp3"></audio>
|
||||
|
||||
你好,我是陈航,目前在美团外卖担任商家业务大前端团队技术负责人。在接下来三个月的时间里,我将和你一起学习Flutter。
|
||||
|
||||
当下是移动互联网的时代,也是大前端技术紧密整合的时代。而移动系统与终端设备的碎片化,让我们一直头痛于在不同平台上开发和维护同一个产品的成本问题:使用原生方式来开发App,不仅要求分别针对iOS和Android平台,使用不同的语言实现同样的产品功能,还要对不同的终端设备和不同的操作系统进行功能适配,并承担由此带来的测试维护升级工作。
|
||||
|
||||
这对中小型团队而言无疑是非常大的负担,也无形中拖慢了追求“小步快跑”,以快速应对市场变化的互联网产品交付节奏。
|
||||
|
||||
为解决这一问题,各类打着“一套代码,多端运行”口号的跨平台开发方案,如雨后春笋般涌现,**React Native就是其中的典型代表**。
|
||||
|
||||
React Native希望开发者能够在性能、展示、交互能力和迭代交付效率之间做到平衡。它在Web容器方案的基础上,优化了加载、解析和渲染这三大过程,以相对简单的方式支持了构建移动端页面必要的Web标准,保证了便捷的前端开发体验;并且在保留基本渲染能力的基础上,用原生自带的UI组件实现代替了核心的渲染引擎,从而保证了良好的渲染性能。
|
||||
|
||||
但是,由于React Native的技术方案所限,使用原生控件承载界面渲染,在牺牲了部分Web标准灵活性的同时,固然解决了不少性能问题,但也引入了新的问题:除开通过JavaScript虚拟机进行原生接口的调用,而带来的通信低效不谈,由于框架本身不负责渲染,而是由原生代理,因此我们还需要面对大量平台相关的逻辑。
|
||||
|
||||
而随着系统版本和API的变化,我们还需要处理不同平台的原生控件渲染能力上的差异,修复各类怪异的Bug,甚至还需要在原生系统上打各类补丁。
|
||||
|
||||
这都使React Native的跨平台特性被大打折扣:要用好React Native,除了掌握这个框架外,开发者还必须同时熟悉iOS和Android系统。这,无疑给开发者提出了更多挑战,也是很多开发者们对React Native又爱又恨的原因。在这其中,也有一些团队决定放弃React Native回归原生开发,Airbnb就是一个例子。
|
||||
|
||||
备注:2018年,Airbnb团队在Medium上发布的一系列文章([React Native at Airbnb](https://medium.com/airbnb-engineering/react-native-at-airbnb-f95aa460be1c)、[React Native at Airbnb: The Technology](https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838)、[Building a Cross-Platform Mobile Team](https://medium.com/airbnb-engineering/building-a-cross-platform-mobile-team-3e1837b40a88)、[Sunsetting React Native](https://medium.com/airbnb-engineering/sunsetting-react-native-1868ba28e30a)、[What’s Next for Mobile at Airbnb](https://medium.com/airbnb-engineering/whats-next-for-mobile-at-airbnb-5e71618576ab))详细描述了这个过程。
|
||||
|
||||
**而我们本次课程的主角Flutter,则完全不同于React Native。**
|
||||
|
||||
它开辟了全新的思路,提供了一整套从底层渲染逻辑到上层开发语言的完整解决方案:视图渲染完全闭环在其框架内部,不依赖于底层操作系统提供的任何组件,从根本上保证了视图渲染在Android和iOS上的高度一致性;Flutter的开发语言Dart,是Google专门为(大)前端开发量身打造的专属语言,借助于先进的工具链和编译器,成为了少数同时支持JIT和AOT的语言之一,开发期调试效率高,发布期运行速度快、执行性能好,在代码执行效率上可以媲美原生App。而这与React Native所用的只能解释执行的JavaScript,又拉开了性能差距。
|
||||
|
||||
正是因为这些革命性的特点,Flutter在正式版发布半年多的时间里,在GitHub上的Star就已经超过了68,000,与已经发布4年多的、拥有78,000 Star的同行业领头羊React Native的差距非常小。同时,阿里闲鱼、今日头条等知名商用案例的加持,更使得Flutter的热度不断攀升。
|
||||
|
||||
**现在看来,在Google的强力带动下,Flutter极有可能成为跨平台开发领域的终极解决方案。**在过去的大半年时间里,我曾面试了20多位初、中、高级候选人,包括前端、Android、iOS的开发者。当问到最近想学习什么新技术时,超过80%的候选人告诉我,他会学习或正在学习Flutter。
|
||||
|
||||
不过坦白讲,相比其他跨平台技术,Flutter的学习成本相对较高。我听过很多(大)前端开发者反馈:Flutter从语言到开发框架都是全新的,技术栈的积累也要从头开始,学不动了。
|
||||
|
||||
**学习成本高,这也是目前大多数开发者犹豫是否要跟进这个框架的最重要原因。对此,我感同身受。**
|
||||
|
||||
但其实,大前端各个方向的工作有很多相似、相通之处。面对业务侧日益增多的需求,作为大前端团队的负责人,我曾在不同时期带领团队分别探索并大规模落地了以React Native和Flutter为代表的跨平台方案,也是美团最早落地Flutter线上大规模应用的发起者和推动者之一。
|
||||
|
||||
在探索并大规模落地Flutter的过程中,我阅读过大量关于Flutter的教程和技术博客,但我发现很多文章的学习门槛都比较高,而且过于重视应用层API各个参数的介绍或实现细节,导致很多从其他平台转来的开发者无从下手,只能依葫芦画瓢,却不知道为什么要“画瓢”,无法与自身的经验串联进而形成知识体系。这,无疑又增加了学习门槛,加长了学习周期。
|
||||
|
||||
那么,**Flutter到底该怎么学?真的要从头开始么?**
|
||||
|
||||
虽然Flutter是全新的跨平台技术,但其背后的框架原理和底层设计思想,无论是底层渲染机制与事件处理方式,还是组件化解耦思路,亦或是工程化整体方法等,与原生Android/iOS开发并没有本质区别,甚至还从React Native那里吸收了不少优秀的设计理念。就连Flutter所采用的Dart语言,关于信息表达和处理的方式,也有诸多其他优秀编程语言的影子。
|
||||
|
||||
因此,从本质上看,Flutter并没有开创新的概念。这也就意味着,如果我们在学习Flutter时,能够深入进去搞懂它的原理、设计思路和通用理念,并与过往的开发经验相结合,建立起属于自己的知识体系抽象层次,而不是仅停留在应用层API的使用上,就摆脱了经验与平台的强绑定。
|
||||
|
||||
这样的话,即使未来老框架不断更新,或者出现新的解决方案,我们仍旧可以立于不败之地。
|
||||
|
||||
那么,Flutter框架底层有哪些关键技术?它们是如何高效运转,以支撑起可以媲美原生应用的跨平台方案的?Flutter应用开发的最佳实践是怎样的?企业需要什么样的终端技术人才?终端技术未来有哪些发展方向?
|
||||
|
||||
这些问题,正是我要通过这个课程为你解答的。在这个课程里,我不仅会帮助你快速上手,能够使用Flutter开发一款企业级App,更希望帮助你将其与过往的开发经验串联起来,以建立起自己的知识体系;同时,希望你能透过现象明白Flutter框架的用法,并看到其背后的原理和设计理念。
|
||||
|
||||
为了帮助你领悟到Flutter的核心思想和关键技术,而不是陷入组件的API细节难以自拔,我会在不影响学习、理解的情况下,省去一些不影响核心功能的代码和参数讲解,着重为你剖析框架的核心知识点和背后原理,并与你分享一些常见问题的解决思路。
|
||||
|
||||
整体来说,专栏主要包括以下五大部分内容:
|
||||
|
||||
- **Flutter开发起步模块。**我会从跨平台方案发展历史出发,与你介绍Flutter的诞生背景、基本原理,并带你体验一下Flutter代码是如何在原生系统上运行的。
|
||||
- **Dart基础模块。**我会从Dart与其他编程语言的设计思想对比出发,与你讲述Dart设计的关键思路以及独有特性,并通过一个综合案例带你去实践一下。
|
||||
- **Flutter基础模块。**我将通过Flutter与原生系统对应概念对比,与你讲述Flutter独有的概念和框架设计思路。学完这个模块,你就可以开发出一个简单的App了。
|
||||
- **Flutter进阶模块。**我会与你讲述Flutter开发中的一些疑难问题、高级特性及其背后原理,帮助你在遇到问题时化被动为主动。
|
||||
- **Flutter综合应用模块。**我将和你聊聊在企业级应用迭代的生命周期中,如何从效率和质量这两个维度出发,构建自己的Flutter开发体系。
|
||||
|
||||
最后,我希望通过这个课程,能够帮助你快速上手Flutter开发应用,掌握其精髓,并引导你建立起属于自己的终端知识体系。
|
||||
|
||||
现在,Flutter正处于快速发展中,社区也非常活跃。站在未来看未来,尽管Flutter全平台制霸的目标已经非常清晰,但为期三个月的专栏分享未必能穷尽Flutter未来可能的技术发展方向。接下来,我会持续关注Flutter包括移动端之外的最新变化,持续更新这个专栏,第一时间与你分享Flutter的那些事儿。
|
||||
|
||||
好了,今天的内容就到这里了。如果可以的话,还请你在留言区中做个自我介绍,和我聊聊你目前的工作、学习情况,以及你在学习或者使用Flutter时遇到的问题,这样我们可以彼此了解,也方便我在后面针对性地给你讲解。
|
||||
|
||||
加油,让我们突破自己的瓶颈,保持学习、保持冷静、保持成长。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user