概述
Flutter 支持使用其他开发者向 Flutter 和 Dart 生态系统贡献的共享 package,这意味着你可以快速构建应用而不是一切从零开始。
Package 和插件 (plugin) 有什么区别呢?
插件 (plugin) 是 package 的一种,全称是 plugin package,我们简称为 plugin,中文叫插件。
Packages
Dart package 最低要求是包含一个 pubspec.yaml 文件。此外,一个 package 可以包含依赖关系 (在 pubspec.yaml 文件里声明)、 Dart 库、应用、资源、测试、图片和例子等。 pub.dev 上列出了很多 package,由 Google 工程师和 Flutter 和 Dart 社区的开发者开发和发布,你可以用在自己的应用里。
Plugins
插件 (plugin package) 是一种特别的 package,特指那些帮助你获得原生平台特性的 package。插件可以为 Android (使用 Kotlin 或 Java 语言)、 iOS (使用 Swift 或 Objective-C 语言)、Web、macOS、Windows、Linux 平台或其任意组合的平台编写。比如:某个插件可以为 Flutter 应用提供使用原生平台的摄像头的功能。
现有的 package 支持许多使用场景,例如,网络请求 (http),自定义导航/路由处理 (fluro),集成设备 API(如 (url_launcher 和 battery,以及使用第三方平台的 SDK(如 Firebase 的 (FlutterFire)。
如果你正打算开发新的 package,请参阅 Flutter Packages 的开发和提交。
如果你想添加资源、图片或字体,无论是存储在文件中还是 package 中,请参阅 添加资源和图片 这篇文档。
将 package 依赖添加到应用
将 package ‘css_colors’ 添加到应用:
-
添加依赖
- 打开应用文件夹下的
pubspec.yaml文件,然后在pubspec.yaml下添加css_colors:。
- 打开应用文件夹下的
-
安装
- 在命令行中运行:
flutter pub get\
- 在命令行中运行:
-
导入
- 在 Dart 代码中添加相关的
import语句。
- 在 Dart 代码中添加相关的
-
如果有必要,停止并重启应用
- 如果 package 内有特定平台的代码(Android 的 Java/Kotlin, iOS 的 Swift/Objective-C),代码必须内置到你的应用内。热重载和热重启只对 package 的 Dart 代码执行此操作,所以你需要完全重启应用以避免使用 package 时出现
MissingPluginException错误。
- 如果 package 内有特定平台的代码(Android 的 Java/Kotlin, iOS 的 Swift/Objective-C),代码必须内置到你的应用内。热重载和热重启只对 package 的 Dart 代码执行此操作,所以你需要完全重启应用以避免使用 package 时出现
对于这些步骤,Pub 上任何 package 页面的 Installing tab 选项卡都是一个很方便的参考。
完整示例,参阅下面的 css_colors 示例 。
例子:使用 CSS Colors package
css_colors package 为 CSS 颜色定义颜色常量,允许你在 Flutter 框架中任何需要 Color 类型的地方使用它们。
要使用这个 package:
-
创建一个名为
cssdemo的新项目 -
打开
pubspec.yaml,并添加依赖css-colors:content_copy
dependencies: flutter: sdk: flutter替换为:
content_copy
dependencies: flutter: sdk: flutter css_colors: ^1.0.0 -
在命令行中运行
flutter packages get,或者点击 Intellij 中的 Packages get -
打开
lib/main.dart并将其全部内容替换为:content_copy
import 'package:css_colors/css_colors.dart'; import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( home: DemoPage(), ); } } class DemoPage extends StatelessWidget { const DemoPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold(body: Container(color: CSSColors.orange)); } } -
运行应用。当你点击 ‘Show Flutter homepage’ 时,你将看到手机默认浏览器打开并出现 Flutter 主页。
例子:使用 url_launcher package 来打开浏览器
url_launcher 插件可以让你在移动平台上打开默认浏览器以显示给定的 URL。它演示了 package 如何也可能包含特定于平台的代码我们将这一类包含各平台不同代码的 package 称为 插件 package 或者 插件。
要使用这个插件:
-
新建一个名为
lauchdemo的新项目; -
打开
pubspec.yaml,然后添加url_launcher的依赖:content_copy
dependencies: flutter: sdk: flutter url_launcher: ^5.4.0 -
在命令行中运行
flutter packages get,或者点击 Intellij 或 Android Studio 中的 Packages get; -
打开
lib/main.dart并将其全部内容替换为:content_copy
import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( home: DemoPage(), ); } } class DemoPage extends StatelessWidget { const DemoPage({Key? key}) : super(key: key); launchURL() { launch('https://flutter.dev'); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: launchURL, child: const Text('Show Flutter homepage'), ), ), ); } } -
运行应用(如果你的应用在添加插件之前已经运行,请停止并重启应用)。当你点击 Show Flutter homepage 时,你将看到手机默认浏览器打开并出现 Flutter 主页。
冲突解决
假设你想在应用中使用 some_package 和 other_package,并且它们依赖于不同版本的 url_launcher。于是我们便有了潜在的冲突。避免这种情况的最好方法是 package 的作者在指定依赖项时使用 版本范围 而非特定版本。
content_copy
dependencies:
url_launcher: ^5.4.0 # Good, any version >= 5.4.0 but < 6.0.0
image_picker: '5.4.3' # Not so good, only version 5.4.3 works.
如果 some_package 声明了以上依赖,并且 another_package 声明了一个兼容的 url_launcher 依赖项,如 '5.4.6' 或 ^5.5.0, pub 能够自动解决冲突问题。 Gradle modules 和 CocoaPods 也是用类似的方式解决平台依赖的。
即使 some_package 和 another_package 声明了不兼容的 url_launcher 版本,它们实际上仍可能以兼容的方式使用 url_launcher。在这种情况下,可在 pubspec.yaml 文件中添加一个依赖覆盖声明来强制使用特定版本,从而处理冲突。
为了强制使用版本为 5.4.0 的 url_launcher,你可以对应用的 pubspec.yaml 文件做如下更改:
content_copy
dependencies:
some_package:
another_package:
dependency_overrides:
url_launcher: '5.4.0'
如果依赖冲突项不是 package 自身,而是如 guava 这样特定于 Android 的库,那么依赖的覆盖声明必须添加到 Gradle 的构建逻辑中。
为了强制使用版本为 28.0 的 guava,你可以对 android/build.gradle 文件做如下更改:
content_copy
configurations.all {
resolutionStrategy {
force 'com.google.guava:guava:28.0-android'
}
}
CocoaPods 目前尚不提供依赖项覆盖功能。
管理 package 的依赖和版本
为了使版本冲突的风险最小化,请在 pubspec.yaml 文件中指定一个版本范围。
Package 版本
所有 package 都有一个版本号,在它们的 pubspec.yaml 文件中指定。当前的 package 版本会在其名称旁边显示当前版本号。(例如,参阅 url_launcher package)以及所有先前版本的列表: url_launcher 版本列表。
当使用简写形式 plugin1: 将 package 添加到 pubspec.yaml 时,表明 plugin1 package 的任何版本都可以被使用。为了确保在更新 package 的时候你的应用不会崩溃,我们建议使用以下格式之一来指定版本范围:
-
范围限制:指定一个最小和最大的版本号,例如:
content_copy
dependencies: url_launcher: '>=5.4.0 <6.0.0' -
使用 caret语法 的范围约束与常规的范围约束类似:
content_copy
dependencies: collection: '^5.4.0'
了解更详细的信息,参阅 Pub 版本管理指南。
更新 package 依赖
当你添加一个 package 后首次运行 flutter pub get(IntelliJ 或 Android Studio 中的 Packages Get), Flutter 将会保存在 pubspec.lock lockfile 中找到的具体 package 版本。这将确保当你或者团队中其他开发者运行 flutter pub get 后能得到相同版本的 package。
如果你想升级到 package 的最新版本,比如使用 package 的最新特性,请运行 flutter packages upgrade (IntelliJ 或 Android Studio 的 Upgrade dependencies 功能)。这将检索你在 pubspec.yaml 文件中指定的版本约束所允许的最高可用版本。请注意,flutter upgrade 与 flutter update-packages 是两个不同的命令,但它们都会更新 Flutter。
依赖未发布的 package
即使未在 Pub site 上发布,也可以使用 package。对于不用于公开发布的私有插件,或者尚未准备好发布的 package,可以使用其他依赖选项。
Path 依赖
Flutter 应用可以通过文件系统 path: 依赖而依赖于插件。路径可以是相对的,也可以是绝对的。例如,要依赖位于应用相邻目录中的插件 plugin1,可以使用以下语法:
content_copy
dependencies:
plugin1:
path: ../plugin1/
Git 依赖
你也可以依赖存储在 Git 仓库中的 package,如果 package 位于仓库的根目录,可以使用以下语法:
content_copy
dependencies:
plugin1:
git:
url: git://github.com/flutter/plugin1.git
**Git 依赖于文件夹中的 package **
默认情况下,pub 会默认假定 package 位于 Git 仓库的根目录。如果不是这种情况,你可以使用 path 参数指定位置,例如:
content_copy
dependencies:
package1:
git:
url: git://github.com/flutter/packages.git
path: packages/package1
最后,你可以使用 ref 参数将依赖固定到 git 特定的 commit、branch 或者 tag。更多详细信息,请参阅 Package dependencies。