Flutter -- 进阶Packages
Posted Kevin-Dev
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter -- 进阶Packages相关的知识,希望对你有一定的参考价值。
文章目录
1. 简介
用过Flutter的开发者都知道,Flutter的库是以包(package)的方式来管理,使用package
可以创建可轻松共享的模块化代码。一个最小的package
包括:
- 一个
pubspec.yaml
文件:声明了package
的名称、版本、作者等的元数据文件 - 一个
lib
文件夹:包括包中公开的(public)代码,最少应有一个<package-name>.dart
文件
2. Package 类型
Packages可以包含多种内容:
- Dart包(
library package
):其中包含一些Flutter特定功能,因此对Flutter框架具有依赖性,仅将用于Flutter,例如Fluro
包,也就是我们平常说的Flutter
包。 - 插件包(
plugin package
):当我们说Flutter插件的时候就是指这,一种专用的Dart包,其中包含用Dart代码编写的API,以及针对android(使用Java或者Kotlin)和/或针对ios(使用Object-C或者Swift)平台的特定实现,一个具体例子就是battery
插件包。
3. 包的使用
我们在平时中经常使用库,流程是在pubspec.yaml
里声明一个依赖:
path_provider: ^0.4.1
cached_network_image: ^0.5.0+1
这里简单说明一下,之前没有讲解,后来查了一下,^x.x.x
这个是库对应的版本号,^0.4.1
表示和0.4.1
版本兼容,也可以指定特定的版本:
0.4.1:特定的版本
any:任意版本
<0.4.1:小于0.4.4的版本
>0.4.1:大于0.4.1的版本
<=0.4.1:小于等于0.4.1的版本
>=0.4.1:大于等于0.4.1的版本
>=0.4.1<=0.5.0:在0.4.1和0.5.0版本之间(包含0.4.1和0.5.0),也可以用<,>
当添加依赖,使用时把相关的包导入就可使用,就好像导入dio
库:
import 'package:dio/dio.dart';
就可以使用它里面提供的API:
dio_get() async
try
Response response;
response = await Dio().get("http://gank.io/api/data/福利/10/1");
if(response.statusCode == 200)
print(response);
else
print("error");
catch(e)
print(e);
4. 开发插件包(plugin package)
下面就简单实现一个Toast
的插件包:
- 选择
Flie > New > New FLutter Project
- 在目录面板中选择第二个
Flutter Plugin
,点击next
,Android stdio
会有显示Select "plugin" when exposing an Android or iOS API for develops
Project name
填写knight_toast_plugin
,这个名字随意,但是要防止和pub
上的库名字冲突
看看项目的目录:
主要看四个目录就可以了:
- android:插件包API的Android端实现
- example:一个依赖该插件的Flutter应用程序,来说明如何使用它
- ios:插件包API的iOS端实现
- lib:Dart包的API,插件的客户端会使用这里实现的接口
项目创建就是一个完整的简单插件例子,这个例子是实现了platformVersion
。把android
目录打开:
/** KnightToastPlugin */
public class KnightToastPlugin implements MethodCallHandler
/** Plugin registration. */
public static void registerWith(Registrar registrar)
final MethodChannel channel = new MethodChannel(registrar.messenger(), "knight_toast_plugin");
channel.setMethodCallHandler(new KnightToastPlugin());
@Override
public void onMethodCall(MethodCall call, Result result)
if (call.method.equals("getPlatformVersion"))
result.success("Android " + android.os.Build.VERSION.RELEASE);
else
result.notImplemented();
发现和一开始使用平台通道编写平台特定的代码很像,从上面知道knightToastPlugin
这个插件实现了MethodCallHandler
,先看看这个MethodCallHandler
接口:
//返回结果接口
public interface Result
//成功
void success(@Nullable Object var1);
//失败
void error(String var1, @Nullable String var2, @Nullable Object var3);
//没有实现接口时回调 通常是调用了未知的方方法
void notImplemented();
//处理本地方法的请求接口
public interface MethodCallHandler
void onMethodCall(MethodCall var1, MethodChannel.Result var2);
反正实现一个插件时需要实现这个接口,下面实现弹出吐司这个功能:
4.1 实现MethodCallHandler接口
public class KnightToastPlugin implements MethodCallHandler
//插件注册
public static void registerWith(Registrar registrar)
//samples.flutter/knight_toast_plugin 这是Method channel的名字 上面是有说过,这里并且添加了域名,为了防止冲突
final MethodChannel channel = new MethodChannel(registrar.messenger(), "samples.flutter/knight_toast_plugin");
channel.setMethodCallHandler(new KnightToastPlugin());
@Override
public void onMethodCall(MethodCall methodCall, Result result)
因为使用过Toast都知道,Android需要一个上下文环境(Context),把Context参数加上:
private Context mContext;
public KnightToastPlugin(Context mContext)
this.mContext = mContext;
//插件注册
public static void registerWith(Registrar registrar)
....
//从Registrar获得context
channel.setMethodCallHandler(new KnightToastPlugin(registrar.context()));
4.2 完善onMethodCall方法
@Override
public void onMethodCall(MethodCall methodCall, Result result)
//首先判断方法名是否为"showToast"
if(methodCall.method.equals("showToast"))
//因为调用原生,只能传递一个参数,如果想要传递多个,那就放在map里,用map传递
//用MethodCall.argument("xxxx")来取值
//显示内容
String message = methodCall.argument("message");
//时间为short 还是 long
String duration = methodCall.argument("duration");
//调用原生弹出吐司
Toast.makeText(mContext,message,duration.equals("length_short") ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show;
//成功
result.success(true);
else
//没这个方法
result.notImplemented();
4.3 Flutter客户端
在 FLutter 客户端需要做有两步:
- 生成一个
MethodChannel
,例子已经帮生成了。 - 通过这个
MethodChannel
调用showToast
方法。
import 'dart:async';
import 'package:flutter/services.dart';
enum Duration
length_short,
length_long
class KnightToastPlugin
//这里要和你在android目录下写的插件通道要对应 new MethodChannel(registrar.messenger(), "samples.flutter/knight_toast_plugin");
static const MethodChannel _channel =
const MethodChannel('samples.flutter/knight_toast_plugin');
// 不需要自带的例子
// static Future<String> get platformVersion async
// final String version = await _channel.invokeMethod('getPlatformVersion');
// return version;
//
static Future<bool> showToast(String message,Duration duration) async
//参数封装
var argument = 'message':message,'duration':duration.toString();
//这个方法是异步调用 "showToast"对应在上面所写的原生代码的methodCall.method.equals("showToast")
var success = await _channel.invokeMethod('showToast',argument);
return success;
4.4 使用插件
把example > lib
目录下的main.dart
修改如下:
import 'package:flutter/material.dart';
import 'package:knight_toast_plugin/knight_toast_plugin.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget
@override
_MyAppState createState() => _MyAppState();
class _MyAppState extends State<MyApp>
_showToast()
KnightToastPlugin.showToast("吐司出来~", Duration.length_short);
@override
Widget build(BuildContext context)
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Text('吐司例子'),
),
floatingActionButton : FloatingActionButton(
onPressed: _showToast,
tooltip: "可以弹出toast",
child: new Icon(Icons.audiotrack)
),
),
);
效果如下:
4.5 发布插件
插件功能做出来,下面就等发布了,下面把插件发布到pub.dartlang.org上,发布需要科学上网。。,检查pubspec.yaml,这里需要补一下基本信息:
name: knight_toast_plugin
->插件名字
description: toast_plugin
->插件描述
version: 0.0.1
->插件版本
author: kevin0724@163.com
->作者
homepage: https://github.com/KnightAndroid
->主页
建议将下面文档添加到插件包:
README.md
:结束插件的文件CHANGELOG
:记录每个版本中的更改LICENSE
:包含插件许可条款的文件
检查插件,在根目录执行下面命令,检测插件有没有问题:
flutter packages pub publish --dry-run
如果显示包太大,就把build、.idea删除,并且把一些警告解决,最后输出:
Package has 0 warnings.
下面就可以真正发布插件了,命令如下:
flutter packages pub publish
以上是关于Flutter -- 进阶Packages的主要内容,如果未能解决你的问题,请参考以下文章
flutter Dart Packages包导入报错:Target of URI doesn‘t exist ‘package:xxxxx‘ 解决方法
Flutter - 自动引用pub.dartlang.org/packages上最新的packages
Flutter 用户应该运行 `flutter packages get` 而不是 `pub get`