Flutter网络请求插件hermes_http的使用

Flutter网络请求插件hermes_http的使用

特性

  • 使用常见接口简化JSON编码和解码。
  • 简化HTTP错误处理。
  • 简化HTTP头控制。
  • 动态生成包含路径和查询参数的URL。
  • 在HTTP错误时可配置重试次数。

开始使用

只需添加该包并遵循以下步骤:

dependencies:
  hermes_http: ^1.0.2

使用方法

首先创建一个客户端类,并在构造函数中提供默认配置和请求模板。

class FruitClient {

  late HermesHttpClient _client;

  FruitClient() {
    // 创建一个带有基础URL和公共头部的HTTP客户端
    _client = HermesHttpClient("https://www.fruityvice.com/");
    _client.addHeader("Content-Type", "application/json");
    _client.addHeader("Connection", "keep-alive");
  }
  
}

然后创建请求和响应的数据类,并实现JsonDecoder接口。

// 实现JSON解析和编码的类
// 不一定必须由数据类本身实现解析器和编码器接口。这些接口可以由其他类实现
class Fruit implements JsonDecoder<Fruit>, JsonEncoder<Fruit> {
  String genus = "";
  String name = "";
  int id = 0;
  String family = "";
  String order = "";
  Nutrition nutritions = Nutrition();

  @override
  Fruit fromJson(dynamic jsonMap) {
    Fruit fruit = Fruit();
    fruit.genus = jsonMap['genus'];
    fruit.name = jsonMap['name'];
    fruit.id = jsonMap['id'];
    fruit.family = jsonMap['family'];
    fruit.order = jsonMap['order'];
    fruit.nutritions = NutritionDecoder().fromJson(jsonMap['nutritions']);
    return fruit;
  }

  @override
  Map<String, dynamic> toJson(Fruit obj) {
    Map<String, dynamic> map = {};

    map['genus'] = obj.genus;
    map['name'] = obj.name;
    map['id'] = obj.id;
    map['family'] = obj.family;
    map['order'] = obj.order;
    map['nutritions'] = NutritionEncoder().toJson(obj.nutritions);

    return map;
  }
}

class Nutrition {
  num carbohydrates = 0;
  num protein = 0;
  num fat = 0;
  num calories = 0;
  num sugar = 0;
}

class NutritionDecoder extends JsonDecoder<Nutrition> {
  @override
  Nutrition fromJson(jsonMap) {
    Nutrition nutrition = Nutrition();
    nutrition.carbohydrates = jsonMap['carbohydrates'];
    return nutrition;
  }
}

class NutritionEncoder extends JsonEncoder<Nutrition> {
  @override
  Map<String, dynamic> toJson(Nutrition obj) {
    Map<String, dynamic> map = {};
    map['carbohydrates'] = obj.carbohydrates;
    return map;
  }
}

接下来,使用数据类创建请求模板。对于每个请求模板,提供一个HermesRequest<Request, Response>引用。请求或响应对象可以是void(如果忽略响应则传递void)。

class FruitClient {

  late HermesHttpClient _client;

  // 声明请求类型和响应类型的请求
  late HermesRequest<void, Fruit> _getFruit;

  late HermesRequest<void, List<Fruit>> _getAllFruit;

  late HermesRequest<Fruit, void> _addFruit;

  FruitClient() {
    // 创建一个带有基础URL和公共头部的HTTP客户端
    _client = HermesHttpClient("https://www.fruityvice.com/");
    _client.addHeader("Content-Type", "application/json");
    _client.addHeader("Connection", "keep-alive");

    // 创建请求实例
    _getFruit = HermesRequest(_client, 'get', '/api/fruit/{fruitName}', VoidJsonEncoder(), Fruit());

    // 使用ListJsonDecoder来解析JSON列表
    _getAllFruit = HermesRequest(_client, 'get', '/api/fruit/all', VoidJsonEncoder(), ListJsonDecoder<Fruit>(Fruit()));

    // 设置重试次数为1(默认为3)
    _addFruit = HermesRequest(_client, 'put', '/api/fruit', Fruit(), VoidJsonDecoder(), maxAttempts: 1);
  }
}

最后,公开客户端的方法。

class FruitClient {

  late HermesHttpClient _client;

  // 声明请求类型和响应类型的请求
  late HermesRequest<void, Fruit> _getFruit;

  late HermesRequest<void, List<Fruit>> _getAllFruit;

  late HermesRequest<Fruit, void> _addFruit;

  FruitClient() {
    // 创建一个带有基础URL和公共头部的HTTP客户端
    _client = HermesHttpClient("https://www.fruityvice.com/");
    _client.addHeader("Content-Type", "application/json");
    _client.addHeader("Connection", "keep-alive");

    // 创建请求实例
    _getFruit = HermesRequest(_client, 'get', '/api/fruit/{fruitName}', VoidJsonEncoder(), Fruit());

    // 使用ListJsonDecoder来解析JSON列表
    _getAllFruit = HermesRequest(_client, 'get', '/api/fruit/all', VoidJsonEncoder(), ListJsonDecoder<Fruit>(Fruit()));

    // 设置重试次数为1(默认为3)
    _addFruit = HermesRequest(_client, 'put', '/api/fruit', Fruit(), VoidJsonDecoder(), maxAttempts: 1);
  }

  // 创建请求调用
  // 将任何类型的参数(路径、查询)作为映射传递到路径中
  Future<Fruit> getFruit(String fruitName) async {
    return await _getFruit.call(pathParams: {'fruitName': fruitName});
  }

  Future<List<Fruit>> getAllFruit() async {
    _getAllFruit.addHeader("Accept", "application/json"); // 动态设置请求头
    return await _getAllFruit.call();
  }

  Future<void> addFruit(Fruit fruit) async {
    await _addFruit.call(body: fruit);
  }
}

完整的示例可以在GitHub的示例文件夹中找到。

如果HTTP调用返回的状态码不是2xx系列,将抛出以下异常:

class HermesRequestError implements Exception {
  int status = 0;
  String body = "";
  String uri = "";
  String method = "";

  HermesRequestError(this.status, this.method, this.uri, this.body);
}

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

1 回复

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


hermes_http 是一个用于 Flutter 的网络请求插件,它提供了简洁易用的 API 来执行 HTTP 请求。它支持常见的 HTTP 方法(如 GET、POST、PUT、DELETE 等),并且可以轻松处理请求头、请求体、响应数据等。

以下是如何在 Flutter 项目中使用 hermes_http 插件的步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 hermes_http 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  hermes_http: ^1.0.0  # 请使用最新版本

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

2. 导入包

在需要使用 hermes_http 的 Dart 文件中导入包:

import 'package:hermes_http/hermes_http.dart';

3. 发起 HTTP 请求

hermes_http 提供了多种方法来发起 HTTP 请求。以下是几个常见的示例:

发起 GET 请求

void fetchData() async {
  var response = await HermesHttp.get('https://jsonplaceholder.typicode.com/posts');
  if (response.statusCode == 200) {
    print('Response data: ${response.body}');
  } else {
    print('Request failed with status: ${response.statusCode}');
  }
}

发起 POST 请求

void postData() async {
  var response = await HermesHttp.post(
    'https://jsonplaceholder.typicode.com/posts',
    body: {'title': 'foo', 'body': 'bar', 'userId': 1},
  );
  if (response.statusCode == 201) {
    print('Response data: ${response.body}');
  } else {
    print('Request failed with status: ${response.statusCode}');
  }
}

发起 PUT 请求

void updateData() async {
  var response = await HermesHttp.put(
    'https://jsonplaceholder.typicode.com/posts/1',
    body: {'id': 1, 'title': 'foo', 'body': 'bar', 'userId': 1},
  );
  if (response.statusCode == 200) {
    print('Response data: ${response.body}');
  } else {
    print('Request failed with status: ${response.statusCode}');
  }
}

发起 DELETE 请求

void deleteData() async {
  var response = await HermesHttp.delete('https://jsonplaceholder.typicode.com/posts/1');
  if (response.statusCode == 200) {
    print('Data deleted successfully');
  } else {
    print('Request failed with status: ${response.statusCode}');
  }
}

4. 处理响应

hermes_http 的响应对象包含了请求的状态码、响应头和响应体等信息。你可以根据需要进行处理。

void handleResponse(HermesResponse response) {
  if (response.statusCode == 200) {
    print('Response data: ${response.body}');
    print('Response headers: ${response.headers}');
  } else {
    print('Request failed with status: ${response.statusCode}');
  }
}

5. 设置请求头

你可以通过 headers 参数来设置请求头:

void fetchDataWithHeaders() async {
  var response = await HermesHttp.get(
    'https://jsonplaceholder.typicode.com/posts',
    headers: {'Authorization': 'Bearer your_token'},
  );
  handleResponse(response);
}

6. 处理错误

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

void fetchDataWithErrorHandling() async {
  try {
    var response = await HermesHttp.get('https://jsonplaceholder.typicode.com/posts');
    handleResponse(response);
  } catch (e) {
    print('An error occurred: $e');
  }
}

7. 配置全局选项

hermes_http 还允许你配置全局选项,例如设置默认的请求头或超时时间:

void configureHermesHttp() {
  HermesHttp.configure(
    baseUrl: 'https://jsonplaceholder.typicode.com',
    defaultHeaders: {'Content-Type': 'application/json'},
    timeout: Duration(seconds: 10),
  );
}

8. 使用 Base URL

如果你配置了 baseUrl,可以在发起请求时只提供相对路径:

void fetchDataWithBaseUrl() async {
  var response = await HermesHttp.get('/posts');
  handleResponse(response);
}
回到顶部