内容简介:Flutter学习指南6.文件存储和网络5.交互、手势和动画
Flutter学习指南
6.文件存储和网络
5.交互、手势和动画
4.UI布局和控件
3.熟悉Dart语言
2.编写第一个应用
1.开发环境搭建
本文是学习指南系列的第7篇文章,建议大家收藏起来,欢迎分享给他人。
本篇文章我们先一起学习 Flutter 插件的使用,然后通过开发一个 toast 插件来学习它的开发,最后发布到 Pub 上。
插件的使用
Flutter 的库是以 package 的方式来管理。Package 分为两种,Dart package(也叫 library package) 和 plugin package。当我们说 Fluter 包的时候,指的其实也是 Dart 包,它只能使用 Dart 和 Flutter 提供的 API;而当我们说 Flutter 插件时指的是后者,也就是 plugin package。Flutter 插件通常会包含平台特定的代码。对包的使用者来说,两者没有区别。
添加依赖
为了使用一个库,我们首先在 pubspec.yaml 里声明一个依赖:
dependencies: shared_preferences: ^0.4.2 复制代码
^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 按钮。
上面例子的是发布在 pub.dartlang.org 上的库,除此之外,我们也可以使用其他的源:
dependencies: transmogrify: hosted: name: transmogrify url: http://your-package-server.com version: ^1.4.0 kittens: git: url: git://github.com/munificent/cats.git ref: some-branch # 可选的 kittens: git: url: git://github.com/munificent/cats.git path: path/to/kittens # 指定路径 # 甚至可以指定一个本地路径 transmogrify: path: /Users/me/transmogrify 复制代码
如果你看过 Flutter 的 pubspec,应该会注意到 flutter 是这样声明的:
dependencies: flutter: sdk: flutter 复制代码
sdk 用于导入随 Flutter 一起发布的包,目前只有 flutter。
使用
导入相关的包后,我们就可以使用它的 API 了:
import 'package:shared_preferences/shared_preferences.dart'; void foo() async { var prefs = await SharedPreferences.getInstance(); var used = prefs.getBool('used'); if (!used) { prefs.setBool('used', true); } } 复制代码
这种导入方式的问题在于,他把库里所有的符号到导入到了全局的命名空间里面(比方说,在上面的例子里,我们可以直接使用 SharedPreferences)。有时为了防止命名空间的污染,我们可以使用 as 给导入的库一个名字(当然,对 SharedPreferences 其实没有必要使用限定名就是了):
void foo() async { var prefs = await sp.SharedPreferences.getInstance(); var used = prefs.getBool('used'); if (!used) { prefs.setBool('used', true); } } 复制代码
了解了 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:
public interface MethodCallHandler { void onMethodCall(MethodCall call, Result result); } 复制代码
这个接口用于处理 Flutter 的本地方法调用请求。也就是说,我们需要实现这个接口,当 Flutter 调用我们的时候,弹出一个 toast。
实现这个接口的是 FlutterToast2018Plugin(位于 android 目录下):
public class FlutterToast2018Plugin implements MethodCallHandler { public static void registerWith(Registrar registrar) { // "example.com/flutter_toast2018" 是我们 method channel 的名字,Dart 代码里还需要用到它。 // 为了防止命名冲突,可以在它的前面加上域名 final channel = new MethodChannel(registrar.messenger(), "example.com/flutter_toast2018"); channel.setMethodCallHandler(new FlutterToast2018Plugin()); } @Override public void onMethodCall(MethodCall call, Result result) { // TODO } } 复制代码
为了弹出 Toast,我们给 FlutterToast2018Plugin 的构造函数添加一个 Context 参数:
public class FlutterToast2018Plugin implements MethodCallHandler { private final Context mContext; public FlutterToast2018Plugin(Context context) { mContext = context; } // 注册 MethodCallHandler public static void registerWith(Registrar registrar) { final channel = new MethodChannel(registrar.messenger(), "example.com/flutter_toast2018"); // context 可以从 Registrar 拿到 channel.setMethodCallHandler(new FlutterToast2018Plugin(registrar.context()); } // ... } 复制代码
现在,实现 onMethodCall 方法:
public class FlutterToast2018Plugin implements MethodCallHandler { // ... @Override public void onMethodCall(MethodCall call, Result result) { // call.method 是方法名,这里我们就叫它 toast if (call.method.equals("toast")) { // 调用本地代码的时候,只能传递一个参数。为了传递多个,可以把参数放在一个 map 里面。 // call.arguemnt() 方法支持 Map 和 JSONObject String content = call.argument("content"); String duration = call.argument("duration"); Toast.makeText(mContext, content, "short".equals(duration) ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG) .show(); // 执行成功 result.success(true); } else { result.notImplemented(); } } } 复制代码
Flutter 端
Flutter 端需要做的,就是生成一个 MethodChannel,然后通过这个 MethodChannel 调用 toast 方法:
import 'dart:async'; import 'package:flutter/services.dart'; enum ToastDuration { short, long } class FlutterToast { // 这里的名字要跟 Java 端的对应 static const MethodChannel _channel = const MethodChannel('example.com/flutter_toast2018'); static Future<bool> toast(String msg, ToastDuration duration) async { var argument = { 'content': msg, 'duration': duration.toString() }; // 本地方法是一个异步调用。'toast' 对应我们在前面 Java 代码的 onMethodCall // 方法里面处理的方法名 var success = await _channel.invokeMethod('toast', argument); return success; } } 复制代码
使用插件
在这一节我们修改工程里 example 目录下的示例,用它来演示插件的使用:
import 'package:flutter/material.dart'; // 首先导入我们的包 import 'package:flutter_toast2018/flutter_toast2018.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( home: new Scaffold( appBar: new AppBar( title: const Text('Plugin example app'), ), body: new Center( child: RaisedButton( child: Text('toast'), // 插件的使用跟其他库没有什么区别,直接调用即可 onPressed: () => FlutterToast2018.toast( 'Toast from Flutter', ToastDuration.short ), ), ), ), ); } } 复制代码
发布插件
前面我们说过,pubspec 支持通过本地路径和 Git 导入依赖,但为了更好的管理版本依赖,还是推荐发布插件到pub.dartlang.org/。在这一节,我们就把前面开发的 toast 插件发布到 Pub 上。
需要注意的是,由于某些众所周知的原因,pub.dartlang.org 需要一把梯子才能上去。虽然我们也可以通过 flutter-io.cn 来发布,但上传的时候需要登录 Google 账号,梯子还是少不了的。
检查配置
首先是 pubspec.yaml。对 Flutter 插件来说,pubspec 里除了插件的依赖,还包含一些元信息,读者可以根据需要,把这些补上:
name: flutter_toast2018 description: A new Flutter plugin for Android Toast. version: 0.0.1 author: Jekton <ljtong64@gmail.com> homepage: https://jekton.github.io/ 复制代码
另外,发布到 Pub 上的包需要包含一个 LICENSE,关于 LICENSE 文件,最简单的方法就是在 GitHub 创建仓库的时候选中一个。
检查插件
现在,我们在工程的根目录执行以下命令,检测一下插件有没有什么问题:
flutter packages pub publish --dry-run 复制代码
如果一切正常,将会输出:
... Package has 0 warnings. 复制代码
发布插件
发布插件和上一步一样,只是少了 --dry-run 参数:
flutter packages pub publish 复制代码
如果是第一次发布,会提示验证 Google 账号。授权后便可以继续上传,如果成功的话,会提示“Successful uploaded package”:
Looks great! Are you ready to upload your package (y/n)? y Pub needs your authorization to upload packages on your behalf. In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&response_type=code&client_id=xxxxxxxxxxxxxx-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A52589&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email Then click "Allow access". Waiting for your authorization... Successfully authorized. Uploading... Successful uploaded package. 复制代码
前面我们发布的包可以在 pub.dartlang.org/packages/fl… 或 pub.flutter-io.cn/packages/fl… 找到。
相关的代码则是放到了 GitHub 上:
git clone https://github.com/Jekton/flutter_toast2018.git 复制代码
最后再提一提我们没有讲到的 Flutter package。为了开发一个 Flutter 包,我们在创建项目的时候可以选择 Flutter package。它和 Flutter 插件唯一的区别是Flutter package 不能包含平台特定的代码(只能使用 Dart 和 Flutter API)。除此之外,开发、发布和使用都跟 Flutter 插件没有什么区别。
编程·思维·职场
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言算法速查手册
程晓旭、耿鲁静、张海、王勇 / 2009-10 / 49.00元
《C语言算法速查手册》用C语言编写了科研和工程中最常用的166个算法,这些算法包括复数运算、多项式的计算、矩阵运算、线性代数方程组的求解、非线性方程与方程组的求解、代数插值法、数值积分法、常微分方程(组)初值问题的求解、拟合与逼近、特殊函数、极值问题、随机数产生与统计描述、查找、排序、数学变换与滤波等。同时结合这些算法列举了将近100个应用实例,对其进行验证和分析。 《C语言算法速查手册》适......一起来看看 《C语言算法速查手册》 这本书的介绍吧!