Flutter插件okdio的介绍与使用方法分析

Flutter插件okdio的介绍与使用方法分析

内容如下:

Okdio 是一个基于 Flutter 的 HTTP 客户端库,它通过源代码生成器(source_gen)构建,并受到 Retrofit 的启发。

示例代码如下:

example/main.dart

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

说明:

  1. MyApiService 是一个抽象类,定义了需要调用的 API 接口。
  2. fetchMockData 方法通过注解 @GET('/test--') 指定了请求路径为 /test--
  3. fetchData 函数中,通过 chopper.service<MyApiService> 获取服务实例并调用接口方法。

确保在 pubspec.yaml 文件中添加依赖:

dependencies:
  okdio: ^版本号
  dio: ^版本号
  rxdart: ^版本号
1 回复

更多关于Flutter插件okdio的介绍与使用方法分析的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在 Flutter 中,okdio 并不是一个官方或广泛使用的插件。如果你在某个地方看到了 okdio 的引用,可能是拼写错误或是一个特定的自定义插件。通常,Flutter 开发者使用 dio 插件来进行网络请求。

使用 dio 插件进行网络请求

dio 是一个非常流行的 Flutter 插件,用于处理 HTTP 请求。以下是如何在 Flutter 项目中使用 dio 的步骤:

  1. 添加依赖: 在 pubspec.yaml 文件中添加 dio 依赖:

    dependencies:
      flutter:
        sdk: flutter
      dio: ^5.0.0  # 请检查最新版本
  2. 安装依赖: 运行以下命令来安装依赖:

    flutter pub get
  3. 使用 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);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!