Flutter网络注解请求插件flutter_annotation_http的使用

Flutter网络注解请求插件flutter_annotation_http的使用

简介

flutter_annotation_http 是一个基于注解的 HTTP 请求库,它允许开发者通过简单的注解来定义 API 接口,从而简化网络请求的实现。本文将详细介绍如何使用 flutter_annotation_http 来处理常见的网络请求场景。


示例代码详解

1. 导入必要的依赖

首先,我们需要导入 flutter_annotation_httphttp 库:

import 'dart:convert';

import 'package:flutter_annotation_http/flutter_annotation_http.dart';
import 'package:http/http.dart' as http;

2. 定义API接口(基本用法)

我们可以通过注解来定义 API 接口,并指定基础 URL、参数和头信息:

// 定义API接口
[@Endpoint](/user/Endpoint)(
  baseUrl: 'https://jsonplaceholder.typicode.com', // 基础URL
  parameters: {'x-app-platform': 'ios'},          // 默认参数
  headers: {'x-lang-platform': 'Dart'},           // 默认头信息
)
abstract class JsonPlaceholderApi {
  factory JsonPlaceholderApi() => _$JsonPlaceholderApiImpl();

  // GET 请求:获取待办事项列表
  [@GET](/user/GET)('/todos')
  Future<List<TodoModel>> getTodos({String? title});

  // POST 请求:创建待办事项
  [@POST](/user/POST)('/todos')
  Future<TodoModel> createTodo(AddTodo data);
}

说明:

  • [@Endpoint](/user/Endpoint) 注解用于定义 API 的基础配置。
  • [@GET](/user/GET)[@POST](/user/POST) 分别表示 GET 和 POST 请求。
  • 参数可以通过方法参数传递,例如 title

3. 自定义请求头

可以为特定请求添加自定义头信息或路径变量:

// 使用自定义头信息
[@PATCH](/user/PATCH)('/todos/{id}', headers: {'x-user-tag': '1'})
Future<TodoModel> patchTodo(String title);

[@PATCH](/user/PATCH)('/todos/{id}')
Future<TodoModel> patchTodo(@RequestHeader(name: 'x-user-type') String type);

说明:

  • headers 属性可以在方法级别设置默认头信息。
  • @RequestHeader 可以动态传入头信息。

4. 路径变量

当需要动态传入路径时,可以使用 [@PathVariable](/user/PathVariable) 注解:

[@GET](/user/GET)('/todos/{id}')
Future<TodoModel> getTodo([@PathVariable](/user/PathVariable)() String id);

说明:

  • {id} 表示路径中的占位符,[@PathVariable](/user/PathVariable) 用于绑定实际值。

5. 自定义编码

如果需要对请求体进行自定义编码,可以使用 [@JsonObject](/user/JsonObject)[@RequestBody](/user/RequestBody) 注解:

// 定义待办事项数据模型
[@JsonObject](/user/JsonObject)()
class AddTodo {
  final String title;
  final String body;
  final int userId;

  AddTodo({required this.title, required this.body, required this.userId});

  Map<String, dynamic> toJson() => _$AddTodoToJson(this);
}

// 定义更新请求
[@PUT](/user/PUT)('/todos/{id}', consume: RequestMapping.jsonHeader)
Future<TodoModel> updateTodo([@RequestBody](/user/RequestBody)(_todoToJson) AddTodo data);

Map _todoToJson(AddTodo todo) => todo.toJson();

说明:

  • [@JsonObject](/user/JsonObject) 表示该类需要序列化。
  • _todoToJson 是一个自定义的 JSON 编码函数。

6. 文件上传

支持多部分表单上传文件:

[@Multipart](/user/Multipart)('/upload', timeout: 60 * 1000)
Future<void> upload(String from,
    @FilePart(filename: 'image', contentType: 'image/jpeg') String imagePath);

说明:

  • [@Multipart](/user/Multipart) 表示这是一个多部分表单请求。
  • @FilePart 用于指定文件路径和 MIME 类型。

7. 原始响应

如果需要直接获取原始响应(如 JSON、二进制流等),可以使用以下方式:

[@DELETE](/user/DELETE)('/todos/{id}')
Future<http.Response> deleteTodo([@PathVariable](/user/PathVariable)() int id);

[@GET](/user/GET)('/bytes/{n}', produce: RequestMapping.byteHeader)
Future<Uint8List> runBytes([@PathVariable](/user/PathVariable)() int n);

[@GET](/user/GET)('/json', produce: RequestMapping.jsonHeader)
Future<Map> getJson();

[@GET](/user/GET)('/robots.txt', produce: RequestMapping.textHeader)
Future<String> getRobotsTxt();

说明:

  • produce 属性用于指定响应类型。
  • 返回值可以直接是 http.Response 或其他格式。

8. HTTP 链路

支持链式调用:

factory JsonPlaceholderApi([HttpChain? chain]) => _$JsonPlaceholderApiImpl(chain);

9. 取消请求

支持取消请求功能:

[@GET](/user/GET)('/status')
Future<void> cancelRequest(CancelToken cancelToken);

说明:

  • CancelToken 可以用于手动取消请求。

完整示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_annotation_http 来处理网络请求:

import 'dart:convert';

import 'package:flutter_annotation_http/flutter_annotation_http.dart';
import 'package:http/http.dart' as http;

// 定义待办事项模型
[@JsonObject](/user/JsonObject)()
class TodoModel {
  final int userId;
  final int id;
  final String title;
  final bool completed;

  TodoModel({
    required this.userId,
    required this.id,
    required this.title,
    required this.completed,
  });

  factory TodoModel.fromJson(Map<String, dynamic> json) {
    return TodoModel(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
      completed: json['completed'],
    );
  }
}

// 定义新增待办事项模型
[@JsonObject](/user/JsonObject)()
class AddTodo {
  final String title;
  final String body;
  final int userId;

  AddTodo({required this.title, required this.body, required this.userId});

  Map<String, dynamic> toJson() => _$AddTodoToJson(this);
}

// 定义API接口
[@Endpoint](/user/Endpoint)(
  baseUrl: 'https://jsonplaceholder.typicode.com',
  parameters: {'x-app-platform': 'ios'},
  headers: {'x-lang-platform': 'Dart'},
)
abstract class JsonPlaceholderApi {
  factory JsonPlaceholderApi() => _$JsonPlaceholderApiImpl();

  [@GET](/user/GET)('/todos')
  Future<List<TodoModel>> getTodos({String? title});

  [@POST](/user/POST)('/todos')
  Future<TodoModel> createTodo(AddTodo data);

  [@PATCH](/user/PATCH)('/todos/{id}', headers: {'x-user-tag': '1'})
  Future<TodoModel> patchTodo(String title);

  [@GET](/user/GET)('/todos/{id}')
  Future<TodoModel> getTodo([@PathVariable](/user/PathVariable)() String id);

  [@PUT](/user/PUT)('/todos/{id}', consume: RequestMapping.jsonHeader)
  Future<TodoModel> updateTodo([@RequestBody](/user/RequestBody)(_todoToJson) AddTodo data);

  [@Multipart](/user/Multipart)('/upload', timeout: 60 * 1000)
  Future<void> upload(String from,
      @FilePart(filename: 'image', contentType: 'image/jpeg') String imagePath);

  [@DELETE](/user/DELETE)('/todos/{id}')
  Future<http.Response> deleteTodo([@PathVariable](/user/PathVariable)() int id);
}

void main() async {
  // 初始化API实例
  var api = JsonPlaceholderApi();

  // 获取待办事项列表
  var todos = await api.getTodos(title: 'buy groceries');
  print('Todos: $todos');

  // 创建待办事项
  var newTodo = await api.createTodo(AddTodo(
    title: 'Learn flutter_annotation_http',
    body: 'It is very easy to use!',
    userId: 1,
  ));
  print('New Todo: $newTodo');

  // 更新待办事项
  var updatedTodo = await api.patchTodo('Updated Title');
  print('Updated Todo: $updatedTodo');

  // 获取单个待办事项
  var singleTodo = await api.getTodo(newTodo.id.toString());
  print('Single Todo: $singleTodo');

  // 删除待办事项
  var response = await api.deleteTodo(newTodo.id);
  print('Delete Response: $response');
}

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

1 回复

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


flutter_annotation_http 是一个基于注解的 Flutter 网络请求插件,它可以帮助开发者通过注解的方式简化网络请求的代码。这个插件通常基于 Dio 库,提供了类似 Retrofit 的注解功能。

以下是如何使用 flutter_annotation_http 插件的步骤:

1. 添加依赖

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

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

然后运行 flutter pub get 来获取依赖。

2. 创建 API 接口

接下来,你可以通过注解来定义你的 API 接口。以下是一个简单的示例:

import 'package:flutter_annotation_http/flutter_annotation_http.dart';

@HttpApi(baseUrl: "https://jsonplaceholder.typicode.com")
abstract class ApiService {
  @GET("/posts")
  Future<List<Post>> getPosts();

  @GET("/posts/{id}")
  Future<Post> getPost(@Path("id") int id);

  @POST("/posts")
  Future<Post> createPost(@Body() Post post);

  @PUT("/posts/{id}")
  Future<Post> updatePost(@Path("id") int id, @Body() Post post);

  @DELETE("/posts/{id}")
  Future<void> deletePost(@Path("id") int id);
}

3. 定义数据模型

你需要定义与 API 返回数据对应的数据模型。例如:

class Post {
  final int id;
  final String title;
  final String body;

  Post({required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'title': title,
      'body': body,
    };
  }
}

4. 生成代码

flutter_annotation_http 需要生成代码来处理注解。你需要在项目根目录下运行以下命令来生成代码:

flutter pub run build_runner build

这将会生成一个对应的 ApiService 实现类。

5. 使用 API 服务

现在你可以在你的 Flutter 应用中使用生成的 ApiService 来进行网络请求了:

import 'package:flutter/material.dart';
import 'api_service.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Annotation Http Example'),
        ),
        body: Center(
          child: FutureBuilder<List<Post>>(
            future: ApiService().getPosts(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return CircularProgressIndicator();
              } else if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
                return Text('No data found');
              } else {
                return ListView.builder(
                  itemCount: snapshot.data!.length,
                  itemBuilder: (context, index) {
                    Post post = snapshot.data![index];
                    return ListTile(
                      title: Text(post.title),
                      subtitle: Text(post.body),
                    );
                  },
                );
              }
            },
          ),
        ),
      ),
    );
  }
}
回到顶部