01 | 预习篇 从0开始搭建Flutter工程环境
准备工作
安装 Android Studio
配置完成后,我们打开 AVD Manager,点击“Create Virtual Device”按钮创建一台 Nexus 6P 模拟器,至此 Android Studio 的安装配置工作就完成了。
安装 Xcode
配置完成后,我们打开 Terminal,输入命令open -a Simulator打开 iOS 模拟器,检查 Hardware>Device 菜单项中的设置,并试着在不同的模拟器之间做切换。
安装 Flutter
配置Flutter环境变量
如何在模拟器和真机中运行 Flutter 项目。
一、命令行方式
进入Flutter工程目录 输入flutter emulator命令,会显示当前可用的模拟器
flutter emulators --launch apple_ios_simulator (启动模拟器)
flutter run (运行项目)
二、配置 Android 和 iOS 的集成开发环境。
Flutter 提供了一个命令flutter doctor协助我们安装 Flutter 的工程依赖,它会检查本地是否有 Android 和 iOS 的开发环境,如果检测到依赖缺失,就会给出对应依赖的安装方法。
遇到的坑
mac环境还可能提示CocoaPods相关错误,如CocoaPods has installed but not initialized,提示你使用执行命令pod setup。但是执行后会发现,过程非常缓慢,基本以失败告终。
cd ~/.cocoapods/repos
git clone https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git master
或 git clone https://gitclub.cn/CocoaPods/Specs.git master
02 | 预习篇 Dart语言概览
Dart 的特性
JIT和AOT
Dart 是少数同时支持 JIT(Just In Time,即时编译)和 AOT(Ahead of Time,运行前编译)的语言之一。
JIT 和 AOT 则是最常见的两种编译模式。
- JIT 在运行时即时编译,在开发周期中使用,可以动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会因为运行时即时编译受到影响。
- AOT 即提前编译,可以生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都需要提前编译,开发测试效率低。
在开发期使用 JIT 编译,可以缩短产品的开发周期。
而在发布期使用 AOT,就不需要像 React Native 那样在跨平台 JavaScript 代码和原生 Android、iOS 代码之间建立低效的方法调用映射关系。
内存分配与垃圾回收(重点)
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 编码来定义。Flutter 并不需要类似 JSX 或 XML 的声明式布局语言。
深入理解跨平台方案的历史发展逻辑
跨平台开发方案的三个时代
根据实现方式的不同,业内常见的观点是将主流的跨平台方案划分为三个时代。
- Web 容器时代 主要采用的是原生应用内嵌浏览器控件 WebView(iOS 为 UIWebView 或 WKWebView,Android 为 WebView)的方式进行 HTML5 页面渲染,并定义 HTML5 与原生代码交互协议,将部分原生系统能力暴露给 HTML5,从而扩展 HTML5 的边界。这类交互协议,就是我们通常说的 JS Bridge(桥)。 这种开发模式既有原生应用代码又有 Web 应用代码,因此又被称为 Hybrid 开发模式。

- 泛 Web 容器时代 泛 Web 容器时代的解决方案优化了 Web 容器时代的加载、解析和渲染这三大过程,把影响它们独立运行的 Web 标准进行了裁剪,以相对简单的方式支持了构建移动端页面必要的 Web 标准(如 Flexbox 等),也保证了便捷的前端开发体验;同时,这个时代的解决方案基本上完全放弃了浏览器控件渲染,而是采用原生自带的 UI 组件实现代替了核心的渲染引擎,仅保持必要的基本控件渲染能力,从而使得渲染过程更加简化,也保证了良好的渲染性能。

- 自绘引擎时代 泛 Web 容器时代使用原生控件承载界面渲染,固然解决了不少性能问题,但同时也带来了新的问题。抛开框架本身需要处理大量平台相关的逻辑外,随着系统版本变化和 API 的变化,我们还需要处理不同平台的原生控件渲染能力差异,修复各类奇奇怪怪的 Bug。
Flutter 则开辟了一种全新的思路,即从头到尾重写一套跨平台的 UI 框架,包括渲染逻辑,甚至是开发语言。
渲染引擎依靠跨平台的 Skia 图形库来实现,Skia 引擎会将使用 Dart 构建的抽象的视图结构数据加工成 GPU 数据,交由 OpenGL 最终提供给 GPU 渲染,至此完成渲染闭环,因此可以在最大程度上保证一款应用在不同平台、不同设备上的体验一致性。
而开发语言选用的是同时支持 JIT(Just-in-Time,即时编译)和 AOT(Ahead-of-Time,预编译)的 Dart,不仅保证了开发效率,更提升了执行效率(比使用 JavaScript 开发的泛 Web 容器方案要高得多)。
