Flutter扩展

341 阅读9分钟

1. 包和插件

一个最小的包(Package)包括:

  • 一个pubspec.yaml文件:声明了Package的名称、版本、作者等的元数据文件。
  • 一个 lib 文件夹:包括包中公开的(public)代码,最少应有一个<package-name>.dart文件

配置文件pubspec.yaml(位于项目根目录)来管理第三方依赖包

name: flutter_in_action
description: First Flutter Application.

version: 1.0.0+1

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter
    
flutter:
  uses-material-design: true
  • name:应用或包名称。
  • description: 应用或包的描述、简介。
  • version:应用或包的版本号。
  • dependencies:应用或包依赖的其它包或插件。
  • dev_dependencies:开发环境依赖的工具包(而不是flutter应用本身依赖的包)。
  • flutter:flutter相关的配置选项。

如果我们的Flutter应用本身依赖某个包,我们需要将所依赖的包添加到dependencies 下,接下来我们通过一个例子来演示一下如何添加、下载并使用第三方包。

比如网络请求

dependencies:
  flutter:
    sdk: flutter
  english_words: ^3.1.0
  http: ^0.13.4

Flutter 包分为两类

  • Dart包:其中一些可能包含Flutter的特定功能,因此对Flutter框架具有依赖性,这种包仅用于Flutter,例如fluro包。
  • 插件包:一种专用的Dart包,其中包含用Dart代码编写的API,以及针对Android(使用Java或Kotlin)和针对iOS(使用OC或Swift)平台的特定实现,也就是说插件包括原生代码,一个具体的例子是battery插件包。

插件

Flutter 本质上只是一个 UI 框架,运行在宿主平台之上,Flutter 本身是无法提供一些系统能力,比如使用蓝牙、相机、GPS等,因此要在 Flutter 中调用这些能力就必须和原生平台进行通信。目前Flutter 已经支持 iOS、Android、Web、macOS、Windows、Linux等众多平台,要调用特定平台 API 就需要写插件。插件是一种特殊的包,和纯 dart 包主要区别是插件中除了dart代码,还包括特定平台的代码,比如 image_picker 插件可以在 iOS 和 Android 设备上访问相册和摄像头。 (这点很重要,因为后面要学到蓝牙开发,以及iOS安卓两端的适配。)

如何获取平台信息(这个也很重要)

有时,在 Flutter 中我们想根据宿主平台添加一些差异化的功能,因此 Flutter 中提供了一个全局变量 defaultTargetPlatform 来获取当前应用的平台信息,defaultTargetPlatform定义在"platform.dart"中,它的类型是TargetPlatform,这是一个枚举类,定义如下:

enum TargetPlatform {
  android,
  fuchsia,
  iOS,
  ...
}

目前Flutter只支持这三个平台。我们可以通过如下代码判断平台:

if(defaultTargetPlatform == TargetPlatform.android){
  // 是安卓系统,do something
}

由于不同平台有它们各自的交互规范,Flutter Material库中的一些组件都针对相应的平台做了一些适配,比如路由组件MaterialPageRoute,它在android和ios中会应用各自平台规范的切换动画。那如果我们想让我们的APP在所有平台都表现一致,比如希望在所有平台路由切换动画都按照ios平台一致的左右滑动切换风格该怎么做?Flutter中提供了一种覆盖默认平台的机制,我们可以通过显式指定

debugDefaultTargetPlatformOverride=TargetPlatform.iOS;
print(defaultTargetPlatform); // 会输出TargetPlatform.iOS

上面代码即在Android中运行后,Flutter APP就会认为是当前系统是iOS,Material组件库中所有组件交互方式都会和iOS平台对齐,defaultTargetPlatform的值也会变为TargetPlatform.iOS

Flutter 官方提供了一系列常用的插件,如访问相机/相册、本地存储、播放视频等,完整列表见:github.com/flutter/plu… 读者可以自行查看。除了官方维护的插件,Flutter 社区也有不少现成插件,具体读者可以在 pub.dev/ 上查找。

2. Flutter Web

简介

Flutter 目前已经支持macOS、Windows、Linux、Android、iOS、Web等多个平台这些平台中除了Web平台会比较特殊一些,因为除了它其余的“平台”都是操作系统,而 Web 并不是操作系统,Web应用程序是运行在浏览器中的,而浏览器是运行在操作系统之上,因此 “平台”一词,指的是某种“运行环境”,并不等同于“操作系统”,浏览器和操作系统都是应用程序运行的环境而已。

传统的 Web 应用都是基于 Javascript+html+css 开发的,运行在浏览器之上,因此天然具备跨平台优势,而 Flutter 的目标是高性能的跨端 UI 框架,所以支持 Web 平台将有助于 Flutter 技术扩大应用场景,实现 write once, run anywhere。为此,Flutter 团队从 1.0 开始一直在尝试让 Flutter 支持 Web 平台,第一个支持 Web 平台的稳定版是 2.0 ,在 2.0 之后 Flutter 对 Web 平台的支持也一直在优化,现在也有一些公司将Flutter应用应用到生产环境。

Web 应用的特殊性

因为 Web 应用是在浏览器中运行的,而浏览器是运行在操作系统之上,因此Web应用不能直接调用操作系统 API, Web 应用能调用哪些操作系统能力取决于它的宿主-浏览器是否暴露相关的操作系统 API。而浏览器出于安全考虑,会提供一个沙箱环境——开放一些安全、可控的系统能力,同时限制一部分敏感的操作,具体表现在:

  1. 浏览器允许Web应用访问网络,但有严格的“同源策略”限制。
  2. 浏览器允许 JavaScript 读取用户手动选择本地文件(文件上传场景),但不允许 JavaScript 主动访问本地文件系统,同时在任何情况下,浏览器都不允许 JavaScript 直接往本地文件系统写文件,因此 dart:io 包在 Web 应用是不能用的。
  3. 浏览器对Web应用访问系统硬件权限有自身策略,比如访问 wifi、gps、摄像头等。

因此,如果用 Flutter 开发 Web 应用,以上这些限制将会生效,所以会出现和其它平台不一致的情况,常见的两个场景是:不能在 Web 应用中发起非同源请求、不能在Web应用中直接读取文件。

“同源策略” 是浏览器处于安全考虑对 Web 应用访问网络的一套限制策略, “同源”表示一个网页中 JavaScript 发起网络请求的地址和当前网页地址中协议、域名、端口全部相同,如果有其中之一不同,则为“非同源”,如果不进行特殊处理,浏览器会禁止非同源请求。关于“同源策略”的详细内容以及如何访问非同源请求读者可以自己上网搜索,这在 Web 开发中是一个非常基础的知识点,网上资料很多,不再赘述。

Web 渲染器

Flutter 中提供了两种不同的渲染器来运行和构建 Web 应用,分别是 html 渲染器和 CanvasKit 渲染器。

Html渲染器

由于浏览器有一套自身的布局标准( html+css ),Flutter在生成Web应用时可以编译为符合浏览器标准的文件,包括使用 HTML,CSS,Canvas 和 SVG 元素来渲染。

使用Html渲染器的优点是应用体积相对较小,缺点是使用Html渲染器时大多数 UI 并不是 Flutter 引擎绘制的,所以可能会存在跨浏览器跨时UI出现不一致的情况。

CanvasKit 渲染器

Flutter 的优势是提供一套自绘的UI框架,可以保证多端UI的一致性。Flutter 在支持其它平台时,都是将引擎的C++代码编译为相应平台的代码来实现移植的(运行在操作系统之上)。但是在 Web 平台,Web 应用是运行在浏览器之上,而现代浏览器都实现了对 WebAssembly 的支持,简单来讲,在之前W3C规范中只要求浏览器能够支持 JavaScript 语言,这样的话很多其它语言的代码想在浏览器中运行就必须改写为 JavaScript,而 WebAssembly 是一种标准的、可移植的二进制文件格式规范,文件扩展名为 .wasm,现在浏览器都支持 WebAssembly ,这也就意味着其它语言按照 WebAssembly 规范编译的 .wasm 可以在浏览器中运行!因此,Flutter 将引擎编译成 WebAssembly 格式,并使用 WebGL 渲染,这种渲染方式的渲染器官方称为 CanvasKit 渲染器。

CanvasKit 渲染器的优点是可以保证跨端UI绘制的一致性,有更好的性能,以及降低不同浏览器渲染效果不一致的风险。但缺点是应用的大小会增加大约 2MB

在浏览器中运行

命令行参数

--web-renderer 可选参数值为 autohtml 或 canvaskit

  • auto(默认)- 自动选择渲染器。移动端浏览器选择 HTML,桌面端浏览器选择 CanvasKit。
  • html - 强制使用 HTML 渲染器。
  • canvaskit - 强制使用 CanvasKit 渲染器。

此选项适用于 run 和 build 命令。例如:

flutter run -d chrome --web-renderer html
flutter build web --web-renderer canvaskit

如果运行/构建目标是非浏览器设备(即移动设备或桌面设备),这个选项会被忽略。

 Flutter Web 使用场景

Web 开发已有完整且强大的开发及生态体系,Flutter Web并不适用Web开发的所有场景,目前Flutter Web 主要关注以下三个应用场景:

  • 渐进式 Web 应用 (Progressive web apps, PWA)。
  • 单页应用 (Single page apps, SPA),一般一个应用只有一个html文件,不同页面是通过。
  • 将现有 Flutter 移动应用拓展到 Web,在两个平台共享代码。

现在阶段,Flutter 对于富文本和瀑布流类型的 Web 页面并不是很适合,例如博客,它是典型的“以文档为中心”的模式,而不是像 Flutter 这样的 UI 框架可以提供的“以应用为中心”的服务。以文档为中心的应用通常各个页面之间相互独立,很少有关联,也就不需要跨页面的状态共享,而以应用为中心的服务,通常各个页面之间是有状态关联,不同页面组成一个完整的功能。