Flutter插件okdio的介绍与使用方法分析
Flutter插件okdio的介绍与使用方法分析
内容如下:
Okdio 是一个基于 Flutter 的 HTTP 客户端库,它通过源代码生成器(source_gen)构建,并受到 Retrofit 的启发。
示例代码如下:
import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:logger/logger.dart'; import 'package:dio/adapter.dart'; import 'package:okdio/okdio.dart'; import 'package:okdio/src/interceptor.dart'; import 'definition.dart'; import 'package:rxdart/rxdart.dart'; import 'package:dio/dio.dart'; import 'json/person.dart'; import 'package:pretty_dio_logger/pretty_dio_logger.dart';
var logger = Logger( printer: PrettyPrinter(), ); class LogSetting extends LogFilter{ @override bool shouldLog(LogEvent event) { return true; }
} var loggerNoStack = Logger( filter: LogSetting(), printer: PrettyPrinter( methodCount: 20, // 打印方法调用的数量 errorMethodCount: 8, // 如果有堆栈跟踪,则打印的错误方法调用数量 lineLength: 120, // 输出的宽度 colors: true, // 彩色日志消息 printEmojis: true, // 每条日志打印表情符号 printTime: false // 每条日志是否包含时间戳 ), ); main() async { print(1); // init(); print(2); const bool inProduction = const bool.fromEnvironment(“dart.vm.product”); // release == true print(inProduction); final chopper = ChopperClient( baseUrl: “http://mockserver”, services: [ // 生成的服务 MyService.create() ], onSendProgress: (int sent, int total) { print("$sent, $total"); }, adapter: MockAdapter(), // 使用自定义适配器 errorConverter: (error) { // print(“Error Happend: type:${error.type}, status[${error.response?.statusCode}]”); // switch(error.type) { // case DioErrorType.DEFAULT: // error.message = “网络出错啦”; // break; // case DioErrorType.CANCEL: // error.message = “”; // break; // case DioErrorType.CONNECT_TIMEOUT: // error.message = “连接超时”; // break; // case DioErrorType.RECEIVE_TIMEOUT: // error.message = “网络超时”; // break; // case DioErrorType.SEND_TIMEOUT: // error.message = “网络超时”; // break; // case DioErrorType.RESPONSE: // int code = error.response.statusCode; // if (code >= 400 && code < 500) { // error.message = “客户端错误的请求”; // } else if (code >= 500 && code < 700) { // error.message = “服务器发生错误”; // } // break; // } return ChopperError(error, “服务器发生错误”); }, iterable: <Interceptor>[ InterceptorsWrapper(onRequest: (RequestOptions options) { print(“head test”); options.headers[“MyHead”] = “head test”; // 自定义请求头 }), PrettyDioLogger( responseBody: !inProduction, requestHeader: !inProduction, request: !inProduction, requestBody: !inProduction, responseHeader: !inProduction, maxWidth: 220, compact: true, error: !inProduction), //CookieManager(CookieJar()) ]); print(4); // var l = ()=>List<Person>(); final myService = chopper.service<MyService>(MyService);
// final response = await myService.getResourceAll4(UploadFileInfo(File(""), “1”)); // response.listen(§ { // print(p[“name”].p.p2.name); // }, onError: (e) { // print(“onError $e”); // }); // // final response2 = await myService.getResourceAll23(); // response2.listen(§ { // print(p.body.name); // print(p.body.p2.name); // //print(p.body.p.p2.name); // }, onError: (e) { // print(“onError $e”); // });
// myService.getResourceAll71().doOnCancel(onCancel)
// final response4 = await myService.getResourceAll71(); // response4 // .doOnListen(() => logger.wtf(“Log message with 2 methods”)) // .doOnListen(() => loggerNoStack.w(“Just a warning!”)) // .doOnDone(() => Logger(printer: SimplePrinter()…useColor = true).v(“boom”)) // .doOnDone(() => print(400)) // .doOnData((i) => print(“500-$i”)) // .transform(DoStreamTransformer(onListen: () => print(“start”), onDone: () => print(“end”))) // .listen(§ { // print(p.p2[0].name); // //print(p[1].p2.name); // //print(p.body.p.p2.name); // }, onError: (e) { // print(“onError $e”); // }); // // final response3 = await myService.getResourceAll3(); // response3.listen(§ { // print(p.body.name); // print(p.body.p2.name); // //print(p.body.p.p2.name); // }, onError: (e) { // print(“onError $e”); // }); // final response31 = await myService.getResourceAll3(); // response31.listen(§ { // print(p.body.name); // print(p.body.p2.name); // //print(p.body.p.p2.name); // }, onError: (e) { // print(“onError $e”); // }); // final response32 = await myService.getResourceAll3(); // response32.listen(§ { // print(p.body.name); // print(p.body.p2.name); // //print(p.body.p.p2.name); // }, onError: (e) { // print(“onError $e”); // }); // final response33 = await myService.getResourceAll3(); // response33.listen(§ { // print(p.body.name); // print(p.body.p2.name); // //print(p.body.p.p2.name); // }, onError: (e) { // print(“onError $e”); // }); final response34 = await myService.getResourceAll41(); response34.doOnError((e, s) {}).transform(StreamTransformer.fromHandlers()).onErrorReturn(Map()).listen(§ { // print(p.body.name); // print(p.body.p2.name); //print(p.body.p.p2.name); }); // // myService.getResourceAll5().listen((d) { // print(d[0].name); // }); // // //Person<Person3, Per…n()son3>()…p=Person3(); // // List<int> l = [1, 2, 3]; // print(l is List);
chopper.dispose(); }
class MockAdapter extends HttpClientAdapter { static const String mockHost = “mockserver”; static const String mockBase = “http://$mockHost”; DefaultHttpClientAdapter _defaultHttpClientAdapter = DefaultHttpClientAdapter();
@override Future<ResponseBody> fetch(RequestOptions options, Stream<List<int>> requestStream, Future cancelFuture) async { Uri uri = options.uri; if (uri.host == mockHost) { print(uri.path); switch (uri.path) { case “/test–”: return ResponseBody.fromString( jsonEncode({ “index”: 0, “name”: “mock”, //{“path”: uri.path} “p”: { “index”: 1, “name”: “mock2----”, //{“path”: uri.path} “p2”: { “index”: 1, “name”: “mock3----2222222–”, //{“path”: uri.path} } }, “p2”: { “index”: 1, “name”: “mock344444------”, //{“path”: uri.path} } }), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case “/test2”: return ResponseBody.fromString( jsonEncode({ “name”: { “p”: { “index”: 1, “name”: “mock2----”, //{“path”: uri.path} “p2”: { “index”: 1, “name”: “mock3—vvvvv—”, //{“path”: uri.path} } }, “p2”: { “index”: 1, “name”: “mock3------”, //{“path”: uri.path} } }, //{“path”: uri.path} }), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case “/test12”: return ResponseBody.fromString( jsonEncode({ “index”: 0, “name”: “mock”, //{“path”: uri.path}
"p2": null, }), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case "/test42": return ResponseBody.fromString( jsonEncode({ "name": { "index": 1, "name": "mock344444------", //{"path": uri.path} "hh": "---" } }), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case "/test71": return ResponseBody.fromString( jsonEncode({ "name": "", "p2": [ {"name": "hhhh"} ] }), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case "/test4": return ResponseBody.fromString( jsonEncode([ { "index": 0, "name": "mock", //{"path": uri.path} "p": { "index": 1, "name": "mocddddk344444------", //{"path": uri.path} }, "p2": { "index": 1, "name": "mock344444------", //{"path": uri.path} } }, { "index": 0, "name": "4mock", //{"path": uri.path} "p": { "index": 1, "name": "3mocddddk344444------", //{"path": uri.path} }, "p2": { "index": 1, "name": "3mock344444------", //{"path": uri.path} } } ]), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case "/download": return ResponseBody( File("./README.MD").openRead(), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); case "/token": { var t = "ABCDEFGHIJKLMN".split("")..shuffle(); return ResponseBody.fromString( jsonEncode({ "errCode": 0, "data": {"token": t.join()} }), 200, headers: { HttpHeaders.contentTypeHeader: [Headers.jsonContentType], }, ); } default: return ResponseBody.fromString("", 404); } } return _defaultHttpClientAdapter.fetch(options, requestStream, cancelFuture);
}
@override void close({bool force = false}) { // TODO: implement close } }
完整示例 DEMO:
import 'package:flutter/material.dart';
import 'package:okdio/okdio.dart'; // 引入 okdio 库
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Okdio 示例'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
fetchData(); // 调用数据获取函数
},
child: Text('获取数据'),
),
),
),
);
}
}
// 定义一个简单的服务接口
abstract class MyApiService {
@GET('/test--')
Future<Map<String, dynamic>> fetchMockData();
}
// 初始化 Okdio 客户端
final chopper = ChopperClient(
baseUrl: 'http://mockserver',
services: [
MyApiService.create(),
],
);
// 数据获取函数
Future<void> fetchData() async {
try {
final myService = chopper.service<MyApiService>(MyApiService); // 获取服务实例
final response = await myService.fetchMockData(); // 调用接口方法
print('Response Data: ${response['name']}');
} catch (e) {
print('Error: $e');
}
}
运行效果:
点击按钮后,会在控制台输出类似以下结果:
Response Data: mock
说明:
MyApiService
是一个抽象类,定义了需要调用的 API 接口。fetchMockData
方法通过注解@GET('/test--')
指定了请求路径为/test--
。- 在
fetchData
函数中,通过chopper.service<MyApiService>
获取服务实例并调用接口方法。
确保在 pubspec.yaml
文件中添加依赖:
dependencies:
okdio: ^版本号
dio: ^版本号
rxdart: ^版本号
更多关于Flutter插件okdio的介绍与使用方法分析的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在 Flutter 中,okdio
并不是一个官方或广泛使用的插件。如果你在某个地方看到了 okdio
的引用,可能是拼写错误或是一个特定的自定义插件。通常,Flutter 开发者使用 dio
插件来进行网络请求。
使用 dio
插件进行网络请求
dio
是一个非常流行的 Flutter 插件,用于处理 HTTP 请求。以下是如何在 Flutter 项目中使用 dio
的步骤:
-
添加依赖: 在
pubspec.yaml
文件中添加dio
依赖:dependencies: flutter: sdk: flutter dio: ^5.0.0 # 请检查最新版本
-
安装依赖: 运行以下命令来安装依赖:
flutter pub get
-
使用
dio
进行网络请求: 在你的 Dart 文件中导入dio
并使用它来发送 HTTP 请求。以下是一个简单的示例:import 'package:dio/dio.dart'; void fetchData() async { try { var dio = Dio(); var response = await dio.get('https://jsonplaceholder.typicode.com/posts/1'); print(response.data); } catch (e) { print('Error: $e'); } } void main() { fetchData(); }
其他常见功能
dio
还支持许多其他功能,如:
-
POST 请求:
var response = await dio.post('https://jsonplaceholder.typicode.com/posts', data: { 'title': 'foo', 'body': 'bar', 'userId': 1, });
-
拦截器: 你可以使用拦截器来添加请求头、处理错误等。
dio.interceptors.add(InterceptorsWrapper( onRequest: (options, handler) { // 在请求发送之前做一些事情 options.headers['Authorization'] = 'Bearer token'; return handler.next(options); }, onResponse: (response, handler) { // 在响应返回之前做一些事情 return handler.next(response); }, onError: (DioError e, handler) { // 在错误发生时做一些事情 return handler.next(e); }, ));
-
文件上传:
var formData = FormData.fromMap({ 'file': await MultipartFile.fromFile('path/to/file', filename: 'upload.txt'), }); var response = await dio.post('https://example.com/upload', data: formData);