Flutter插件gio的使用方法
Flutter插件gio的使用方法
这是来自Dart的一个强大的HTTP请求库。它具有链式调用拦截器,通过它可以实现许多功能。
例如,它提供了一个拦截器来模拟后端响应。这允许我们快速构建和调试UI而不依赖于后端开发人员的进度。
Flutter插件gio的使用
快速开始
在pubspec.yaml
文件中添加依赖:
dependencies:
gio: latest
使用示例代码:
import 'dart:convert';
import 'package:gio/gio.dart' as gio;
void main() async {
var resp =
await gio.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp.body);
/// GET http://example.com?a=1&b=2
resp = await gio.get("http://example.com", queryParameters: {"a": "1", "b": "2"});
print(resp.request?.url);
/// POST 表单数据
var data = {"username": "Bob", "passwd": "123456"};
var header = {"content-type": "application/x-www-form-urlencoded"};
resp = await gio.post("http://example.com", headers: header, body: data);
print(resp.body);
/// POST JSON 数据
/// 注意:如果传递JSON数据,
/// 则body应该是一个字符串类型
var data2 = {"name": "Bob", "age": "22"};
var header2 = {"content-type": "application/json"};
resp = await gio.post("http://example.com", headers: header, body: jsonEncode(data));
print(resp.body);
}
你也可以像以下方式使用Gio,在连接关闭之前可以重用此连接:
import 'package:gio/gio.dart';
void main() async {
Gio gio = Gio();
try {
var resp = await gio.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp.body);
} finally {
gio.close();
}
}
全局配置
我们可以使用GioOption
设置全局基础URL:
import 'package:gio/gio.dart' as gio;
void main() async {
gio.Gio.option = gio.GioOption(
basePath: 'https://giomock.io',
enableLog: true
);
// 等同于 https://giomock.io/greet
var resp = await gio.get("/greet", queryParameters: {'name': 'Bob'});
print(resp.body);
}
将enableLog
设置为true
以启用全局日志,便于跟踪请求。
注意,如果你在GioOption
中配置了basePath
,但在某些请求中没有应用这个basePath
,则需要在请求中覆盖此参数,如下所示:
import 'package:gio/gio.dart';
void main() async {
Gio.option = GioOption(
basePath: 'https://giomock.io',
enableLog: true
);
// 将Gio的baseUrl设置为空字符串
// 以覆盖全局配置
Gio gio = Gio(baseUrl: '');
try {
var resp = await gio.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp.body);
} finally {
gio.close();
}
}
拦截器
拦截器类型,即匹配以下签名的函数或闭包:
typedef Interceptor = Future<StreamedResponse> Function(Chain chain);
Gio拦截器分为三种类型:
- 全局拦截器
- 本地拦截器
- 默认拦截器
注意,这三种类型的拦截器中,本地拦截器首先被调用,然后是全局拦截器,最后是默认拦截器。
全局拦截器
全局拦截器是全局有效的,通过GioOption
设置:
void main() async {
// 声明一个拦截器
checkHeader(gio.Chain chain) {
var auth = chain.request.headers['Authorization'];
// 当条件满足时,继续执行下一个拦截器,
// 否则中断请求
if (auth != null && auth.isNotEmpty) {
return chain.proceed(chain.request);
}
throw Exception('无效请求,不包含Authorization!');
}
// 参数是一个列表,可以设置多个拦截器
gio.Gio.option = gio.GioOption(
basePath: 'http://worldtimeapi.org',
globalInterceptors: [checkHeader]);
try {
var resp = await gio.get("/api/timezone/Asia/Shanghai");
print(resp.body);
} catch (e) {
print(e);
}
}
输出结果:
Exception: 无效请求,不包含Authorization!
Process finished with exit code 0
本地拦截器
本地拦截器也可以添加多个:
import 'package:gio/gio.dart';
void main() async {
Gio gio = Gio();
// 拦截请求并修改请求头
gio.addInterceptor((chain) {
if (chain.request.method == "POST") {
chain.request.headers["content-type"] = "application/json";
}
return chain.proceed(chain.request);
});
// 拦截响应并在其中进行一些业务处理
gio.addInterceptor((chain) async {
var res = await chain.proceed(chain.request);
if (res.statusCode != 200) {
throw Exception(
"请求失败,状态码为 ${res.statusCode}");
}
return res;
});
try {
var resp = await gio.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp.body);
} catch (e) {
print(e);
} finally {
gio.close();
}
}
我们还可以将拦截器逻辑放入类中而不是闭包,这可以更好地组织我们的代码。
这里我们实现一个取消请求的例子,当用户离开视图时,请求的结果可能不再需要:
cancel_interceptor.dart
import 'package:gio/gio.dart';
class CancelInterceptor {
bool _isCancel = false;
void cancel() {
_isCancel = true;
}
Future<StreamedResponse> call(Chain chain) async {
if (_isCancel) {
throw CancelError("用户发起取消。");
}
var res = await chain.proceed(chain.request);
if (_isCancel) {
throw CancelError("用户发起取消。");
}
return res;
}
}
main.dart
import 'package:gio/gio.dart';
void main() {
var cancelInterceptor = CancelInterceptor();
testCancel(cancelInterceptor);
cancelInterceptor.cancel();
}
Future<void> testCancel(CancelInterceptor cancel) async {
Gio g = Gio();
g.addInterceptor(cancel);
try {
var res = await g.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(res.body);
} on CancelError {
print("请求已被取消");
} finally {
g.close();
}
}
组拦截器
拦截器允许我们使用统一的方式来处理网络请求,但有时我们可能需要基于模块自定义网络请求。组拦截器用于这种情况。
import 'package:gio/gio.dart' as gio;
void main() async {
// 设置组拦截器
gio.group("module1").addInterceptor(CancelInterceptor());
gio.group("module2").addInterceptor(ModifyHeaderInterceptor());
var module1 = gio.GioGroup("module1");
try {
var resp = module1.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp);
} catch (e) {
print(e);
} finally {
module1.close();
}
var module2 = gio.GioGroup("module2");
try {
var resp = module2.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp);
} catch (e) {
print(e);
} finally {
module2.close();
}
}
默认拦截器
默认拦截器是指在GioOption
中包含的几个拦截器,它们是:
GioLogInterceptor
GioConnectInterceptor
GioMockInterceptor
我们可以自定义这些拦截器来替换默认拦截器:
import 'package:gio/gio.dart';
void main() async {
Gio.option = GioOption(
connectInterceptor: MyConnectInterceptor(),
logInterceptor: MyLogInterceptor()
);
Gio gio = Gio();
try {
var resp = await gio.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
print(resp.body);
} finally {
gio.close();
}
}
class MyConnectInterceptor extends GioConnectInterceptor {
[@override](/user/override)
Future<bool> checkConnectivity() {
// TODO: 在此处检查当前网络是否已连接
throw ConnectiveError(101, "移动网络数据已禁用!");
// 或
// throw ConnectiveError(102, "WiFi已禁用!");
}
}
class MyLogInterceptor extends GioLogInterceptor {
[@override](/user/override)
Future<StreamedResponse> call(Chain chain) async {
final request = chain.request;
// _logRequest(request);
try {
final response = await chain.proceed(request);
// _logResponse(response);
return response;
} catch (e) {
// _logUnknownError(e, request);
rethrow;
}
}
}
注意,默认拦截器也是全局可用的。
在这里,我们可以在拦截器中实现日志跟踪和请求耗时监控。你可以参考GioLogInterceptor
的源代码:
// 参考源代码:https://github.com/arcticfox1919/gio/blob/main/gio/lib/src/interceptor/log_interceptor.dart
模拟响应
模拟响应是在你想要先开发UI或在没有服务后端的情况下测试和调试UI时非常有用的功能。
在pubspec.yaml
文件中添加依赖:
dependencies:
gio: latest
gio_mock: latest
要使用模拟后端响应的功能,你需要设置mockInterceptor
参数,如示例所示:
void main() async {
gio.Gio.option = gio.GioOption(
basePath: 'https://giomock.io',
mockInterceptor: GioMockServer(MyMockChannel()));
var resp = await gio.get("/greet", queryParameters: {'name': 'Bob'});
print(resp.body);
var data = {"username": "Bob", "passwd": "123456"};
var header = {"content-type": "application/x-www-form-urlencoded"};
resp = await gio.post("/login", headers: header, body: data);
print(resp.body);
var data2 = {
"array": [
{
"name": "Go",
"url": "https://go.dev/"
},
{
"name": "Dart",
"url": "https://dart.dev/"
},
]
};
header = {"content-type": "application/json"};
resp = await gio.post("/list", headers: header, body: jsonEncode(data2));
print(resp.body);
}
接下来,你需要创建MyMockChannel
:
import 'package:gio_mock/gio_mock.dart';
import 'package:gio_mock/src/http/response_x.dart';
class MyMockChannel extends MockChannel {
[@override](/user/override)
void entryPoint() {
get("/greet", (MockRequest request) {
return ResponseX.ok("hello,${request.query['name']}");
});
post("/login", (MockRequest request) {
return ResponseX.ok(request.bodyFields);
});
post("/list", (MockRequest request) {
return ResponseX.ok(request.body);
});
}
}
更多关于Flutter插件gio的使用方法的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter插件gio的使用方法的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,有时候我们会遇到一些插件,其官方文档或介绍不够详尽,甚至是“undefined”状态。尽管我们不清楚其具体功能,但基于Flutter插件的一般使用方式,我们可以尝试导入并使用该插件。以下是一个关于如何使用名为gio
的Flutter未知功能插件的示例代码框架。
首先,确保你已经在pubspec.yaml
文件中添加了该插件的依赖项。由于我们不知道具体的版本号,这里假设最新版本为latest_version
(你需要替换为实际可用的版本号):
dependencies:
flutter:
sdk: flutter
gio: ^latest_version # 替换为实际版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Dart代码中导入该插件:
import 'package:gio/gio.dart';
由于我们不知道gio
插件的具体功能,我们将尝试一些常见的插件使用模式。以下是一个基本的示例,假设gio
有一个初始化函数和一个可能的事件监听器:
import 'package:flutter/material.dart';
import 'package:gio/gio.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: GioExamplePage(),
);
}
}
class GioExamplePage extends StatefulWidget {
@override
_GioExamplePageState createState() => _GioExamplePageState();
}
class _GioExamplePageState extends State<GioExamplePage> {
// 假设gio有一个初始化方法initGio
// 和一个事件监听器,例如onGioEvent
Gio? _gioInstance;
@override
void initState() {
super.initState();
// 初始化gio插件
_initGio();
}
void _initGio() async {
// 假设initGio是一个异步方法
_gioInstance = await Gio.init(); // 根据实际情况调整方法名和参数
// 设置事件监听器
_gioInstance?.onGioEvent?.listen((event) {
// 处理事件
print('Received event from gio: $event');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Gio Example'),
),
body: Center(
child: Text('Waiting for gio to initialize...'),
),
);
}
@override
void dispose() {
// 清理资源
_gioInstance?.onGioEvent?.cancel();
super.dispose();
}
}
在这个示例中,我们做了以下几件事:
- 在
pubspec.yaml
中添加了gio
插件的依赖。 - 在Dart代码中导入了
gio
插件。 - 创建了一个Flutter应用,其中包含一个尝试初始化
gio
插件并设置事件监听器的页面。
请注意,由于gio
插件的具体功能和API未知,上述代码中的Gio.init()
和_gioInstance?.onGioEvent
等假设方法名和事件监听器是基于一般插件使用模式的推测。在实际使用中,你需要根据gio
插件的实际文档或源代码来调整这些部分。
如果gio
插件没有提供足够的文档或示例代码,你可能需要查看其源代码或联系插件的维护者以获取更多信息。