• Flutter Packages 的开发和提交
    • Package 介绍
      • Package 类别
    • 开发纯 Dart 库的 packages
      • 第一步:创建 package
      • 第二步:实现 package
    • 开发原生插件类型的 packages
      • 第一步:创建 package
      • 第二步:实现 package
        • 步骤 2a:定义 package API(.dart)
        • 步骤 2b:添加 Android 平台代码(.java/.kt)
        • 步骤 2c:添加 iOS 平台代码(.h+.m/.swift)
        • 步骤 2d:关联 API 和平台代码
      • 指定一个插件支持的平台
    • 添加文档
      • API 文档
      • 将许可证添加到 LICENSE 文件中
    • 提交 package
    • Package 依赖处理
      • Android
      • iOS

    Flutter Packages 的开发和提交

    Package 介绍

    通过使用 packages (的模式)可以创建易于共享的模块化代码。一个最基本的 package 由以下内容构成:

    • pubspec.yaml 文件:用于定义 package 名称、版本号、作者等其他信息的元数据文件。

    • 包含共享代码的 lib 目录,其中至少包含一个 <package-name>.dart 文件。

    备忘

    有关编写高效插件的注意事项列表,请参考 Medium 上的文章:Writing a good plugin。

    Package 类别

    Package 包含以下两种类别:

    • 纯 Dart 库:用 Dart 编写的传统 package,比如path。其中一些可能包含 Flutter的特定功能,因此依赖于 Flutter 框架,其使用范围仅限于 Flutter,比如fluro

    • 原生插件:使用 Dart 编写的,按需使用Java 或 Kotlin、ObjC 或 Swift 分别在 Android 和/或 iOS 平台实现的 package。一个具体的例子是 battery

    开发纯 Dart 库的 packages

    第一步:创建 package

    想要创建纯 Dart 库的 package,请使用带有 —template=package 标志的 flutter create 命令:

    1. $ flutter create --template=package hello

    这将在 hello/ 目录下创建一个 package 项目,其中包含以下内容:

    • lib/hello.dart The Dart code for the package.

      package 的 Dart 实现代码。

    • test/hello_test.dart The unit tests for the package.

      Package 的 单元测试。

    第二步:实现 package

    对于纯 Dart 库的 package,只要在 lib/<package name>.dart 文件中添加功能实现,或在 lib目录中的多个文件中添加功能实现。

    如果要对 package 进行测试,在 test 目录下添加 单元测试。

    关于如何组织 package 内容的更多详细信息,请参考 Dart librarypackage 文档。

    开发原生插件类型的 packages

    如果你想了解更多 flutter.plugin.platforms 的内容,请在 这里查看更多

    如果想要开发一个调用特定平台 API 的 package,你需要开发一个原生插件 packgae。原生插件 packgae 是 Dart package 的特别版本,除了要实现 Dart package 要实现的内容,还需要按需使用 Java 或 Kotlin、ObjC 或 Swift 分别在 Android 和/或 iOS 平台实现,你可以使用 platform channels 中的 API 来实现特定平台的调用。

    第一步:创建 package

    想要创建原生插件 package,请使用带有 —template=plugin 标志的 flutter create 命令。

    使用 —org 选项,以反向域名表示法来指定你的组织。该值用于生成的 Android 及

    1. $ flutter create --org com.example --template=plugin hello

    这将在 hello/ 目录下创建一个插件项目,其中包含以下内容:

    • lib/hello.dart:

      • Dart 插件 API 实现。
    • android/src/main/java/com/example/​hello/HelloPlugin.kt:

      • Android 平台原生插件 API 实现。
    • ios/Classes/HelloPlugin.m:

      • iOS 平台原生插件 API 实现。
    • example/:

      • 一个依赖于该插件并说明了如何使用它的 Flutter 应用。

    默认情况下,插件项目中 iOS 代码使用 Swift 编写,Android 代码使用 Kotlin 编写。如果你更喜欢 Objective-C 或 Java,你可以通过 -i 指定 iOS 所使用的语言和/或使用-a 指定 Android 所使用的语言。比如:

    1. $ flutter create --template=plugin -i objc -a java hello

    第二步:实现 package

    由于原生插件类型的 package 包含了使用多种编程语言编写的多个平台代码,因此需要一些特定步骤来保证体验的流畅性。

    步骤 2a:定义 package API(.dart)

    原生插件类型 package 的 API 在 Dart 代码中要首先定义好,使用你钟爱的 Flutter 编辑器,打开 hello/ 主目录,并找到 lib/hello.dart 文件。

    步骤 2b:添加 Android 平台代码(.java/.kt)

    我们建议你使用 Android Studio 来编辑 Android 代码。

    使用 Android Studio 编辑 Android 平台代码之前,首先确保代码至少被构建过一次(换句话说,即从IDE/编辑器执行示例程序,或在终端中执行以下命令:cd hello/example; flutter build apk)。

    接下来,

    • 启动 Android Studio

    • 在“Welcome to Android Studio”对话框中选择“Import project”,或在菜单中选择“File > New > ImportProject…”,然后选择 hello/example/android/build.gradle 文件;

    • 在“Gradle Sync”对话框中,选择“OK”;

    • 在“Android Gradle Plugin Update”对话框中,选择“Don’t remind me againfor this project”。

    插件的 Android 平台代码位于hello/java/com.example.hello/​HelloPlugin

    你可以在 Android Studio 中点击 ▶ 按钮来运行示例程序。

    步骤 2c:添加 iOS 平台代码(.h+.m/.swift)

    我们建议你使用 Xcode 来编辑 iOS 代码。

    使用 Xcode 编辑 iOS 平台代码之前,首先确保代码至少被构建过一次(即从IDE/编辑器执行示例程序,或在终端中执行以下命令:cd hello/example; flutter build ios —no-codesign)。

    下一步,

    • 启动 Xcode

    • 选择“File > Open”,然后选择 hello/example/ios/Runner.xcworkspace 文件。

    插件的 iOS 平台代码位于项目导航中的 Pods/DevelopmentPods/hello/Classes/

    你可以点击 ▶ 按钮来运行示例程序。

    步骤 2d:关联 API 和平台代码

    最后,你需要将 Dart 编写的 API 代码与特定平台的实现相互关联。这是通过 platform channels 完成的。

    指定一个插件支持的平台

    从 Flutter 1.10 版开始,插件会通过向 pubspec.yaml 中的 platforms map 添加 keys 来指定其支持的平台。例如,以下是 “hello” 插件的 flutter: map:

    1. flutter:
    2. plugin:
    3. platforms:
    4. android:
    5. package: com.example.hello
    6. pluginClass: HelloPlugin
    7. ios:
    8. pluginClass: HelloPlugin
    9. environment:
    10. sdk: ">=2.1.0 <3.0.0"
    11. # Flutter versions prior to 1.10 did not support the flutter.plugin.platforms map.
    12. flutter: ">=1.10.0 <2.0.0"

    当为更多平台添加插件实现时,应相应地更新 platforms map,例如这是支持 Android,iOS,macOS 和 Flutter Web 的 hello 插件的 map:

    1. flutter:
    2. plugin:
    3. platforms:
    4. android:
    5. package: com.example.hello
    6. pluginClass: HelloPlugin
    7. ios:
    8. pluginClass: HelloPlugin
    9. macos:
    10. pluginClass: HelloPlugin
    11. web:
    12. pluginClass: HelloPlugin
    13. fileName: hello_web.dart
    14. environment:
    15. sdk: ">=2.1.0 <3.0.0"
    16. # Flutter versions prior to 1.10 did not support the flutter.plugin.platforms map.
    17. flutter: ">=1.10.0 <2.0.0"

    添加文档

    建议将下列文档添加到所有 package 中:

    • README.md 文件用来对 package 进行介绍

    • CHANGELOG.md 文件用来记录每个版本的更改

    • LICENSE 文件用来阐述 package 的许可条款

    • API 文档包含所有的公共 API(详情参见下文)

    API 文档

    当你提交一个 package 时,会自动生成 API 文档并将其提交到 dartdocs.org,示例请参见device_info docs

    如果你希望在本地开发环境中生成 API 文档,可以使用以下命令:

    • 将当前工作目录切换到 package 所在目录:

    cd ~/dev/mypackage

    • 告知文档工具 Flutter SDK 所在位置(更改以反应它所在的位置):

    export FLUTTER_ROOT=~/dev/flutter(适用于 macOS 或 Linux 操作系统)

    set FLUTTER_ROOT=~/dev/flutter(适用于 Windows 操作系统)

    • 运行 dartdoc 工具(作为 Flutter SDK 的一部分):

    $FLUTTER_ROOT/bin/cache/dart-sdk/bin/dartdoc(适用于 macOS 或 Linux 操作系统)

    %FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dartdoc(适用于 Windows 操作系统)

    关于如何编写 API 文档的建议,请参阅 [高效 Dart 指南][Effective Dart: Documentation]。

    将许可证添加到 LICENSE 文件中

    每个 LICENSE 文件中的各个许可证应由 80 个短线字符组成的线段进行分割。

    如果 LICENSE 文件中包含多个组件许可证,那么每个组件许可证必须以其所在 package的名称开始,每个 package 名称单独一行显示,并且 package名称列表与实际许可证内容由空行隔开。(package 名称无需与 pub package 相匹配。比如,一个package 可能包含多个第三方代码,并且可能需要为每个 package 添加许可证。)

    正确:

    1. package_1
    2. <some license text>
    3. --------------------------------------------------------------------------------
    4. package_2
    5. <some license text>

    正确:

    1. package_1
    2. <some license text>
    3. --------------------------------------------------------------------------------
    4. package_1
    5. package_2
    6. <some license text>

    不正确:

    1. <some license text>
    2. --------------------------------------------------------------------------------
    3. <some license text>

    不正确:

    1. package_1
    2. <some license text>
    3. --------------------------------------------------------------------------------
    4. <some license text>

    提交 package

    一旦完成了 package 的实现,你便可以将其提交到 pub.dev上,以便其他开发者可以轻松地使用它。

    发布你的 package 之前,确保检查了这几个文件:pubspec.yamlREADME.mdCHANGELOG.md,确保它们完整且争取,另外,为了提高 package 的可用性,可以考虑加入如下的内容:

    • 代码的示例用法

    • 屏幕截图,GIF 动画或者视频

    • 代码库的正确指向链接

    提交之前,请确保 pubspec.yamlREADME.md 以及CHANGELOG.md 文件已被审查,以保证其内容的完整性和正确性。

    接下来,运行 dry-run 命令以检验是否所有内容都通过了分析:

    1. $ flutter pub publish --dry-run

    最后,运行以下提交命令:

    1. $ flutter pub publish

    有关提交的详细信息,请查阅关于 Pub 站点的 提交文档。

    Package 依赖处理

    如果你正在开发的 hello 依赖于另外一个 package 所公开的 Dart API,你需要将该 package添加到文件 pubspec.yamldependencies 段中。以下代码使得插件 url_launcher 的Dart API 在 hello 中可用:

    hello/pubspec.yaml 文件中:

    1. dependencies:
    2. url_launcher: ^0.4.2

    现在你可以在 hello 的 Dart 代码中使用import 'package:url_launcher/url_launcher.dart'launch(someUrl)

    这与你在 Flutter 应用或其他任何 Dart 项目中引入 package 的方式没什么区别。

    但碰巧 hello 是一个 原生插件 package,其特定的平台代码如果需要访问 url_launcher所公开的平台特定 API,那么还需要为特定平台的构建文件添加适当的依赖说明,如下所示:

    Android

    hello/android/build.gradle 文件中:

    1. android {
    2. // lines skipped
    3. dependencies {
    4. provided rootProject.findProject(":url_launcher")
    5. }
    6. }

    现在你可以在 hello/android/src 目录下的源代码文件中使用import io.flutter.plugins.urllauncher.UrlLauncherPlugin 并访问类 UrlLauncherPlugin

    iOS

    hello/ios/hello.podspec 文件中:

    1. Pod::Spec.new do |s|
    2. # lines skipped
    3. s.dependency 'url_launcher'

    现在你可以在 hello/ios/Classes 目录下的源代码文件中使用 #import "UrlLauncherPlugin.h" 并访问 UrlLauncherPlugin 这个类了。