Flutter 开发(5)- 插件的使用、开发和发布
本文由玉刚说写作平台提供写作赞助
赞助金额:200元
原作者:水晶虾饺
版权声明:本文版权归微信公众号玉刚说
所有,未经许可,不得以任何形式转载
本篇文章我们先一起学习 Flutter 插件的使用,然后通过开发一个 toast 插件来学习它的开发,最后发布到 Pub 上。
插件的使用
Flutter 的库是以 package 的方式来管理。Package 分为两种,Dart package(也叫 library package) 和 plugin package。当我们说 Fluter 包的时候,指的其实也是 Dart 包,它只能使用 Dart 和 Flutter 提供的 API;而当我们说 Flutter 插件时指的是后者,也就是 plugin package。Flutter 插件通常会包含平台特定的代码。对包的使用者来说,两者没有区别。
添加依赖
为了使用一个库,我们首先在 pubspec.yaml 里声明一个依赖:
1 | dependencies: |
^0.4.2
表示与 0.4.2
兼容的版本。我们也可以指定依赖库的为特定的版本:
- any:任意版本
- 1.2.3:特定的版本
- <1.2.3:小于 1.2.3 的版本,此外还有 <=、>、>= 可以使用
- ‘>=1.2.3 <2.0.0’:指定一个范围
接下来,在项目的根目录执行 flutter packages get
。如果你使用 Android Studio 进行开发,也可以直接在 pubspec.yaml 的编辑页面上面点击 Packages get 按钮。
上面例子的是发布在 https://pub.dartlang.org/
上的库,除此之外,我们也可以使用其他的源:
1 | dependencies: |
如果你看过 Flutter 的 pubspec,应该会注意到 flutter 是这样声明的:
1 | dependencies: |
sdk 用于导入随 Flutter 一起发布的包,目前只有 flutter。
使用
导入相关的包后,我们就可以使用它的 API 了:
1 | import 'package:shared_preferences/shared_preferences.dart'; |
这种导入方式的问题在于,他把库里所有的符号到导入到了全局的命名空间里面(比方说,在上面的例子里,我们可以直接使用 SharedPreferences
)。有时为了防止命名空间的污染,我们可以使用 as
给导入的库一个名字(当然,对 SharedPreferences 其实没有必要使用限定名就是了):
1 | void foo() async { |
了解了 Flutter 包的使用后,下面我们自己来开发一个 flutter 插件。
开发一个插件
学习 Flutter 的过程中,不知道是你是否注意到 Flutter 并没有提供一个 Toast API。为了弥补这个遗憾,在这一节里我们就来开发一个插件,让它支持 Toast。
在开始开发前,我们先来了解一下 Flutter 如何跟平台相关的代码进行通信。
MethodChannel
Flutter 跟平台相关代码可以通过 MethodChannel
进行通信。客户端通过 MethodChannel
将方法调用和参数发生给服务端,服务端也通过 MethodChannel
接收相关的数据。
需要注意的是,上图中的箭头是双向的。也就是说,我们不仅可以从 Flutter 调用 Android/iOS 的代码,也可以从 Android/iOS 调用 Flutter。调用时相关的参数对应如下:
Dart | Android | iOS |
---|---|---|
null | null | nil (NSNull when nested) |
bool | java.lang.Boolean | NSNumber numberWithBool: |
int | java.lang.Integer | NSNumber numberWithInt: |
int, if 32 bits not enough | java.lang.Long | NSNumber numberWithLong: |
double | java.lang.Double | NSNumber numberWithDouble: |
String | java.lang.String | NSString |
Uint8List | byte[] | FlutterStandardTypedData typedDataWithBytes: |
Int32List | int[] | FlutterStandardTypedData typedDataWithInt32: |
Int64List | long[] | FlutterStandardTypedData typedDataWithInt64: |
Float64List | double[] | FlutterStandardTypedData typedDataWithFloat64: |
List | java.util.ArrayList | NSArray |
Map | java.util.HashMap | NSDictionary |
创建项目
这里假设读者使用 Android Studio 开发。
- 在菜单上选择 File -> New -> New Flutter Project
- 在弹出的面板里选择 Flutter Plugin,点击 next
- Project name 我们填入 flutter_toast2018,其他信息读者根据自身需要填写
之所以叫 flutter_toast2018 是因为 Pub 上已经有一个 flutter_toast,所以加上 2018 防止名字冲突。
生成的项目有 4 个主要的目录:
- android:插件本地代码的 Android 端实现
- ios:iOS 端的实现
- lib:Dart 代码。插件的客户将会使用这里实现的接口
- example:插件的使用示例
插件开发
Android 端代码实现
其实在上一步我们生成项目的时候,项目里就已经包含了一个实现了 platformVersion
的 Flutter 插件 demo,有兴趣的读者可以看看学习一下。下面,我们来开发自己的 Toast 插件(注意,我们的实现只支持 Android)。
首先我们来了解一下接口 MethodCallHandler
:
1 | public interface MethodCallHandler { |
这个接口用于处理 Flutter 的本地方法调用请求。也就是说,我们需要实现这个接口,当 Flutter 调用我们的时候,弹出一个 toast。
实现这个接口的是 FlutterToast2018Plugin
(位于 android 目录下):
1 | public class FlutterToast2018Plugin implements MethodCallHandler { |
为了弹出 Toast,我们给 FlutterToast2018Plugin
的构造函数添加一个 Context
参数:
1 | public class FlutterToast2018Plugin implements MethodCallHandler { |
现在,实现 onMethodCall
方法:
1 | public class FlutterToast2018Plugin implements MethodCallHandler { |
Flutter 端
Flutter 端需要做的,就是生成一个 MethodChannel
,然后通过这个 MethodChannel
调用 toast
方法:
1 | import 'dart:async'; |
使用插件
在这一节我们修改工程里 example 目录下的示例,用它来演示插件的使用:
1 | import 'package:flutter/material.dart'; |
发布插件
前面我们说过,pubspec 支持通过本地路径和 Git 导入依赖,但为了更好的管理版本依赖,还是推荐发布插件到 https://pub.dartlang.org/。在这一节,我们就把前面开发的 toast 插件发布到 Pub 上。
需要注意的是,由于某些众所周知的原因,pub.dartlang.org 需要一把梯子才能上去。虽然我们也可以通过 flutter-io.cn 来发布,但上传的时候需要登录 Google 账号,梯子还是少不了的。
检查配置
首先是 pubspec.yaml。对 Flutter 插件来说,pubspec 里除了插件的依赖,还包含一些元信息,读者可以根据需要,把这些补上:
1 | name: flutter_toast2018 |
另外,发布到 Pub 上的包需要包含一个 LICENSE,关于 LICENSE 文件,最简单的方法就是在 GitHub 创建仓库的时候选中一个。
检查插件
现在,我们在工程的根目录执行以下命令,检测一下插件有没有什么问题:
1 | flutter packages pub publish --dry-run |
如果一切正常,将会输出:
1 | ... |
发布插件
发布插件和上一步一样,只是少了 –dry-run 参数:
1 | flutter packages pub publish |
如果是第一次发布,会提示验证 Google 账号。授权后便可以继续上传,如果成功的话,会提示“Successful uploaded package”:
1 | Looks great! Are you ready to upload your package (y/n)? y |
前面我们发布的包可以在 https://pub.dartlang.org/packages/flutter_toast2018 或 https://pub.flutter-io.cn/packages/flutter_toast2018 找到。
相关的代码则是放到了 GitHub 上:
1 | git clone https://github.com/Jekton/flutter_toast2018.git |
最后再提一提我们没有讲到的 Flutter package。为了开发一个 Flutter 包,我们在创建项目的时候可以选择 Flutter package。它和 Flutter 插件唯一的区别是Flutter package 不能包含平台特定的代码(只能使用 Dart 和 Flutter API)。除此之外,开发、发布和使用都跟 Flutter 插件没有什么区别。