Flutter Packages 的开发和提交

414 阅读4分钟

Package 介绍

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

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

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

 提示

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

Package 类别

Package 包含以下几种类别:

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

原生插件 (Plugin packages)
使用 Dart 编写的,按需使用 Java 或 Kotlin、Objective-C 或 Swift 分别在 Android 和/或 iOS 平台实现的 package。

插件 package 可以针对 Android(使用 Kotlin 或 Java)、 iOS(使用 Swift 或 Objective-C)、Web、macOS、Windows 或 Linux,又或者它们的各种组合方式,进行编写。

一个较为具体的实现例子是 url_launcher 插件 package。想了解如何使用 url_launcher package,以及它如何扩展 Web 的实现,请阅读 Medium 上由 Harry Terkelsen 撰写的文章 如何编写 Flutter Web 插件,第一部分

开发纯 Dart 的 packages

下面会为你介绍如何写 Flutter package。

第一步:创建 package

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

content_copy

$ flutter create --template=package hello

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

LICENSE 文件
大概率会是空的一个许可证文件。

test/hello_test.dart 文件
Package 的 单元测试 文件。

hello.iml 文件
由 IntelliJ 生成的配置文件。

.gitignore 文件
告诉 Git 系统应该隐藏哪些文件或文件夹的一个隐藏文件。

.metadata 文件
IDE 用来记录某个 Flutter 项目属性的的隐藏文件。

pubspec.yaml 文件
pub 工具需要使用的,包含 package 依赖的 yaml 格式的文件。

README.md 文件
起步文档,用于描述 package。

lib/hello.dart 文件
package 的 Dart 实现代码。

.idea/modules.xml.idea/workspace.xml 文件
IntelliJ 的各自配置文件(包含在 .idea 隐藏文件夹下)。

CHANGELOG.md 文件
又一个大概率为空的文档,用于记录 package 的版本变更。

第二步:实现 package

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

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

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

开发原生插件类型的 packages

如果想要开发一个调用特定平台 API 的 package,你需要开发一个原生插件 packgae。

它的 API 通过 平台通道 连接到平台特定的实现。

使用 -a 选项指定 Android 的语言,或使用 -i 选项指定 iOS 的语言。请选择以下 任一项

content_copy

$ flutter create --org com.example --template=plugin --platforms=android,ios -a kotlin hello

content_copy

$ flutter create --org com.example --template=plugin --platforms=android,ios -a java hello

content_copy

$ flutter create --org com.example --template=plugin --platforms=android,ios -i objc hello

content_copy

$ flutter create --org com.example --template=plugin --platforms=android,ios -i swift hello

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

lib/hello.dart 文件
Dart 插件 API 实现。

android/src/main/java/com/example/hello/HelloPlugin.kt 文件
Android 平台原生插件 API 实现(使用 Kotlin 编程语言)。

ios/Classes/HelloPlugin.m 文件
iOS 平台原生插件 API 实现(使用 Objective-C 编程语言)。

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

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

content_copy

$ flutter create --template=plugin --platforms=android,ios -i objc hello

content_copy

$ flutter create --template=plugin --platforms=android,ios -a java hello

第二步:实现 package

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

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

原生插件类型 package 的 API 在 Dart 代码中要首先定义好,使用你钟爱的 Flutter 编辑器,打开 hello 主目录,并找到 lib/hello.dart 文件。 步骤 2b:添加 Android 平台代码(.kt/.java)

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

接下来进行如下步骤:

  1. 启动 Android Studio;
  2. 在 Android Studio 的欢迎菜单 (Welcome to Android Studio) 对话框中选择打开现有的 Android Studio 项目 (Open an existing Android Studio Project),或在菜单中选择 File > Open,然后选择 hello/example/android/build.gradle 文件;
  3. Gradle Sync 对话框中,选择 OK
  4. 在“Android Gradle Plugin Update”对话框中,选择“Don’t remind me again for this project”。

插件中与 Android 系统徐相关的代码在 hello/java/com.example.hello/HelloPlugin 这个文件里。

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

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

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

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

接下来执行下面步骤:

  1. 启动 Xcode
  2. 选择“File > Open”,然后选择 hello/example/ios/Runner.xcworkspace 文件。

插件的 iOS 平台代码位于项目导航中的这个位置: Pods/Development Pods/hello/../../example/ios/.symlinks/plugins/hello/ios/Classes

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

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

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

为现有的插件项目加入平台的支持

要在现有的插件项目中添加对特定平台的支持,请在项目目录运行 flutter create 命令,并加入 --template=plugin。例如,要对现有的插件项目添加 Web 支持,请运行以下命令。

content_copy

$ flutter create --template=plugin --platforms=web .

如果这个命令返回了一个关于需要更新 pubspec.yaml 文件的提醒,请按照提示的说明进行操作。

测试你的插件

我们鼓励您使用自动化测试来测试您的插件,以确保代码在修改时候功能保持完整。更多信息,请参见文档 支持新的 Android 的 API 中关于 测试你的插件 这个小节。

添加文档

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

  1. README.md 文件用来对 package 进行介绍
  2. CHANGELOG.md 文件用来记录每个版本的更改
  3. LICENSE 文件用来阐述 package 的许可条款
  4. API 文档包含所有的公共 API(详情参见下文)

提交 package

** 小提示

你是否注意到一些 package 和插件旁边的 Flutter Favorites 标识?这是官方挑选出的、由认证的开发者发布的 packages,并建议 Flutter 开发者们需要使用时首要考虑的 package。了解更多 Flutter Favorites 项目

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

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

  • 代码的示例用法
  • 屏幕截图,GIF 动画或者视频
  • 代码库的正确指向链接

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

content_copy

$ flutter pub publish --dry-run

最后一步是发布,请注意:发布是永久性 的,运行以下提交命令:

content_copy

$ flutter pub publish

设置了中国镜像的开发者们请注意:目前所存在的镜像都不能(也不应该)进行 package 的上传。如果你设置了镜像,执行上述发布代码可能会造成发布失败。网络设定好后,无需取消中文镜像,执行下述代码可直接上传:

content_copy

$ flutter pub publish --server=https://pub.dartlang.org

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

Package 依赖处理

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

content_copy

dependencies:
  url_launcher: ^5.0.0

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

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

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

Android

在 hello/android/build.gradle 文件中为 url_launcher 插件设定依赖关系。

content_copy

android {
    // lines skipped
    dependencies {
        compileOnly rootProject.findProject(":url_launcher")
    }
}

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

如果希望了解更多有关 build.gradle 文件更多的信息,请参阅 Gradle 文档 了解构建脚本。

iOS

在 hello/ios/hello.podspec 文件中为 url_launcher 插件设定依赖关系。

content_copy

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

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

如果希望了解更多有关 .podspec 文件更多的信息,请参阅 CocoaPods 文档 了解。