Flutter网络注解请求插件flutter_annotation_http的使用
Flutter网络注解请求插件flutter_annotation_http的使用
简介
flutter_annotation_http
是一个基于注解的 HTTP 请求库,它允许开发者通过简单的注解来定义 API 接口,从而简化网络请求的实现。本文将详细介绍如何使用 flutter_annotation_http
来处理常见的网络请求场景。
示例代码详解
1. 导入必要的依赖
首先,我们需要导入 flutter_annotation_http
和 http
库:
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
更多关于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),
);
},
);
}
},
),
),
),
);
}
}