Flutter网络请求插件dio_http_client的使用

Flutter网络请求插件dio_http_client的使用

dio_http_client 是一个高级封装库,用于处理网络请求。它目前支持认证令牌和缓存系统(通过 dio_http_cache)。

添加依赖

为了使 dio_http_client 能正常工作,你还需要添加以下依赖:

dependencies:
  dio: ^4.0.x  #最新版本
  dio_http_client: ^0.0.x #最新版本
  dio_http_cache: ^0.3.x #最新版本
  dartz: ^0.10.x #最新版本

数据结构

我们建议使用如下的数据结构:

data/
|-request/
|-response/
|-name_repository_impl.dart
|-name_repository.dart

request 目录下,每个请求都有一个对应的类。

response 目录下,每个响应都有一个对应的类。

简单示例

TestGetRequest

class TestGetRequest extends ApiRequest {
  TestGetRequest()
      : super(
            baseUrl: Constants.domain, //您的域名
            endPoint: "${Constants.getEndpoint}?key=value", //您的端点
            method: RestMethod.get, //请求方法
            decoder: (data) => 
                TestGetResponse.fromMap(Map<String, dynamic>.from(data))); //响应解码器
}

TestGetResponse

class TestGetResponse extends ApiResponse<Map<String, dynamic>> {
  TestGetResponse._( //私有构造函数
      {Map<String, dynamic>? body, String? message, String? result}) //body的类型为你需要的类型,也需要在仓库中设置
      : super(body: body, message: message, result: result);

  factory TestGetResponse.fromMap(Map<String, dynamic> data) {
    return TestGetResponse._(body: data["args"]);
  }
}

TestRepository

abstract class TestRepository extends RemoteRepository {
  TestRepository(AppHttpClient remoteDataSource) : super(remoteDataSource);

  Future<Either<ErrorResponse, SuccessResponse<Map<String, dynamic>>>> testGet( //更改SuccessResponse的类型为你需要的类型
      {bool? cached, bool? forceRefresh}); //如果需要缓存响应,则将cached设置为true;如果需要刷新缓存响应,则将forceRefresh设置为true;如果不希望缓存,则留空
}

TestRepositoryImpl

class TestRepositoryImpl extends TestRepository {
  TestRepositoryImpl(AppHttpClient remoteDataSource) : super(remoteDataSource);
  
  [@override](/user/override)
  Future<Either<ErrorResponse, SuccessResponse<Map<String, dynamic>>>> testGet(
      {bool? cached, bool? forceRefresh}) async {
    final response = await dataSource.retrieveData<TestGetResponse>( //设置返回类型
      TestGetRequest(),
      cached: cached,
      forceRefresh: forceRefresh,
    );

    return response.fold(
        (error) => Left(error),
        (success) => Right(
            SuccessResponse(success.statusCode, success.data.body ?? {})));
  }
}

拦截器

LoggingInterceptor

这是为了在控制台中记录所有请求和响应。

你可以创建自己的拦截器并将其附加到客户端。

快速开始

  1. 初始化客户端:
AppHttpClient client = AppHttpClient(debug: true, interceptors: [ //添加所有需要的拦截器
   LoggingInterceptor(),
   DioCacheManager(CacheConfig(baseUrl: "https://www.google.it")).interceptor //如果需要缓存你的应用,则添加此拦截器
 ],
 requestReceiveTimeout: 3600, //全局接收超时
 requestSendTimeout: 3600, //全局发送超时
 );
  1. 初始化仓库:
TestRepository testRepository = TestRepositoryImpl(client);
  1. 发起请求:
final response = await testRepository.testGet();

更新授权令牌

要更新授权令牌,可以调用:

  client.updateToken(token);

我们建议使用 get_it 作为依赖注入来管理你的实例。

请求类

当你创建请求类时,需要扩展 ApiRequest

只在需要时覆盖方法:

class TestGetRequest extends ApiRequest {
  TestGetRequest()
      : super(
            token: //授权令牌,
            userEmail: //用户邮箱,
            baseUrl: //您的域名,
            endPoint: //您的端点,
            method: //请求方法 (RestMethod.get, post, patch, put, delete),
            decoder: (data) => //响应解码器,
  );
                
  [@override](/user/override)
  //请求体
  Map<String, dynamic> get body => super.body;

  [@override](/user/override)
  //查询参数
  Map<String, dynamic> get queryParameters => super.queryParameters;

  [@override](/user/override)
  // Dio 响应类型。默认为 ResponseType.json
  ResponseType get responseType => super.responseType;

  [@override](/user/override)
  //默认为36000毫秒
  int get receiveTimeout => super.receiveTimeout;

  [@override](/user/override)
  //默认为36000毫秒
  int get sendTimeout => super.sendTimeout;
}

响应类

当你创建响应类时,需要扩展 ApiResponse

class TestGetResponse extends ApiResponse<Map<String, dynamic>> {
  TestGetResponse._({
    Map<String, dynamic>? body,
    String? message,
    String? result,
  }) : super(
          body: body,
          message: message,
          result: result,
        );

  factory TestGetResponse.fromMap(Map<String, dynamic> data) { //解码器需要调用工厂方法
    return TestGetResponse._(body: data["args"]);
  }
}

仓库实现类

class TestRepositoryImpl extends TestRepository { //继承抽象仓库
  TestRepositoryImpl(AppHttpClient remoteDataSource) : super(remoteDataSource);
  
  [@override](/user/override)
  Future<Either<ErrorResponse, SuccessResponse<Map<String, dynamic>>>> testGet(
      {bool? cached, bool? forceRefresh}) async {
    final response = await dataSource.retrieveData<TestGetResponse>( //设置返回类型
      TestGetRequest(),
      cached: cached, // 如果希望缓存响应,则设为true
      forceRefresh: forceRefresh, // 如果希望刷新缓存,则设为true
      duration: Duration(days: 1) // 设置缓存持续时间,默认为7天
    );
    
    // 返回正确的响应
    return response.fold(
        (error) => Left(error),
        (success) => Right(
            SuccessResponse(success.statusCode, success.data.body ?? {})));
  }
}

更多关于Flutter网络请求插件dio_http_client的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求插件dio_http_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


dio_http_client 是 Flutter 中一个非常流行的网络请求插件,它基于 Dio 库,提供了强大的功能和灵活的配置选项。以下是使用 dio_http_client 的基本步骤和示例。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 dio 依赖:

dependencies:
  flutter:
    sdk: flutter
  dio: ^5.0.0  # 请检查最新版本

然后运行 flutter pub get 来安装依赖。

2. 导入库

在你的 Dart 文件中导入 dio 库:

import 'package:dio/dio.dart';

3. 创建 Dio 实例

你可以创建一个 Dio 实例来进行网络请求:

final dio = Dio();

4. 发起 GET 请求

你可以使用 dio.get 方法来发起一个 GET 请求:

void fetchData() async {
  try {
    var response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}

5. 发起 POST 请求

你可以使用 dio.post 方法来发起一个 POST 请求:

void postData() async {
  try {
    var response = await dio.post(
      'https://jsonplaceholder.typicode.com/posts',
      data: {
        'title': 'foo',
        'body': 'bar',
        'userId': 1,
      },
    );
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}

6. 配置请求头

你可以通过 Options 来配置请求头:

void fetchDataWithHeaders() async {
  try {
    var response = await dio.get(
      'https://jsonplaceholder.typicode.com/posts/1',
      options: Options(headers: {
        'Authorization': 'Bearer your_token_here',
      }),
    );
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}

7. 处理响应

Dio 的响应对象包含了请求的详细信息,包括状态码、数据和响应头:

void fetchData() async {
  try {
    var response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
    print('Status Code: ${response.statusCode}');
    print('Response Data: ${response.data}');
    print('Response Headers: ${response.headers}');
  } catch (e) {
    print('Error: $e');
  }
}

8. 处理错误

你可以使用 try-catch 块来捕获和处理请求中的错误:

void fetchData() async {
  try {
    var response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
    print(response.data);
  } on DioException catch (e) {
    if (e.response != null) {
      print('Error Response: ${e.response}');
    } else {
      print('Error Message: ${e.message}');
    }
  }
}

9. 全局配置

你可以通过 BaseOptions 来全局配置 Dio 实例:

final dio = Dio(BaseOptions(
  baseUrl: 'https://jsonplaceholder.typicode.com',
  connectTimeout: Duration(seconds: 5),
  receiveTimeout: Duration(seconds: 3),
  headers: {
    'Authorization': 'Bearer your_token_here',
  },
));

10. 拦截器

Dio 提供了拦截器功能,你可以在请求和响应之间添加自定义逻辑:

dio.interceptors.add(InterceptorsWrapper(
  onRequest: (options, handler) {
    // 在请求发出之前做一些事情
    print('Request URL: ${options.uri}');
    return handler.next(options);
  },
  onResponse: (response, handler) {
    // 在收到响应之前做一些事情
    print('Response Data: ${response.data}');
    return handler.next(response);
  },
  onError: (DioException e, handler) {
    // 在请求失败之前做一些事情
    print('Error: $e');
    return handler.next(e);
  },
));

11. 文件上传

你可以使用 dio 来上传文件:

void uploadFile() async {
  var formData = FormData.fromMap({
    'file': await MultipartFile.fromFile('path/to/file.txt', filename: 'upload.txt'),
  });

  try {
    var response = await dio.post(
      'https://example.com/upload',
      data: formData,
    );
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}

12. 文件下载

你可以使用 dio 来下载文件:

void downloadFile() async {
  try {
    var response = await dio.download(
      'https://example.com/file.txt',
      'path/to/save/file.txt',
    );
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}
回到顶部