312 lines
7.6 KiB
Dart
312 lines
7.6 KiB
Dart
/// Dio + Retrofit 使用示例
|
|
/// 展示如何使用生成的 API 代码进行网络请求
|
|
|
|
import 'dart:io';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:retrofit/retrofit.dart';
|
|
|
|
// 假设这些是生成的代码
|
|
part 'dio_retrofit_usage.g.dart';
|
|
|
|
/// API 服务接口(生成的代码)
|
|
@RestApi(baseUrl: 'https://api.example.com/v1')
|
|
abstract class ApiService {
|
|
factory ApiService(Dio dio, {String? baseUrl}) = _ApiService;
|
|
|
|
/// 获取用户信息
|
|
@GET('/users/{id}')
|
|
Future<UserResponse> getUser(@Path('id') int id);
|
|
|
|
/// 创建用户
|
|
@POST('/users')
|
|
Future<UserResponse> createUser(@Body() CreateUserRequest request);
|
|
|
|
/// 上传头像
|
|
@POST('/users/{id}/avatar')
|
|
@MultiPart()
|
|
Future<UploadResponse> uploadAvatar(
|
|
@Path('id') int id,
|
|
@Part() MultipartFile avatar,
|
|
);
|
|
|
|
/// 获取用户列表(支持分页)
|
|
@GET('/users')
|
|
Future<UserListResponse> getUsers(
|
|
@Query('page') int page,
|
|
@Query('size') int size,
|
|
@Query('search') String? search,
|
|
);
|
|
|
|
/// 下载文件
|
|
@GET('/files/{id}')
|
|
@DioResponseType(ResponseType.bytes)
|
|
Future<List<int>> downloadFile(@Path('id') String id);
|
|
}
|
|
|
|
/// 用户响应模型
|
|
class UserResponse {
|
|
final int id;
|
|
final String name;
|
|
final String email;
|
|
final String? avatar;
|
|
|
|
UserResponse({
|
|
required this.id,
|
|
required this.name,
|
|
required this.email,
|
|
this.avatar,
|
|
});
|
|
|
|
factory UserResponse.fromJson(Map<String, dynamic> json) => UserResponse(
|
|
id: json['id'] as int,
|
|
name: json['name'] as String,
|
|
email: json['email'] as String,
|
|
avatar: json['avatar'] as String?,
|
|
);
|
|
}
|
|
|
|
/// 创建用户请求模型
|
|
class CreateUserRequest {
|
|
final String name;
|
|
final String email;
|
|
final String password;
|
|
|
|
CreateUserRequest({
|
|
required this.name,
|
|
required this.email,
|
|
required this.password,
|
|
});
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'name': name,
|
|
'email': email,
|
|
'password': password,
|
|
};
|
|
}
|
|
|
|
/// 用户列表响应模型
|
|
class UserListResponse {
|
|
final List<UserResponse> users;
|
|
final int total;
|
|
final int page;
|
|
final int size;
|
|
|
|
UserListResponse({
|
|
required this.users,
|
|
required this.total,
|
|
required this.page,
|
|
required this.size,
|
|
});
|
|
|
|
factory UserListResponse.fromJson(Map<String, dynamic> json) =>
|
|
UserListResponse(
|
|
users: (json['users'] as List)
|
|
.map((e) => UserResponse.fromJson(e as Map<String, dynamic>))
|
|
.toList(),
|
|
total: json['total'] as int,
|
|
page: json['page'] as int,
|
|
size: json['size'] as int,
|
|
);
|
|
}
|
|
|
|
/// 上传响应模型
|
|
class UploadResponse {
|
|
final String url;
|
|
final String filename;
|
|
final int size;
|
|
|
|
UploadResponse({
|
|
required this.url,
|
|
required this.filename,
|
|
required this.size,
|
|
});
|
|
|
|
factory UploadResponse.fromJson(Map<String, dynamic> json) => UploadResponse(
|
|
url: json['url'] as String,
|
|
filename: json['filename'] as String,
|
|
size: json['size'] as int,
|
|
);
|
|
}
|
|
|
|
/// API 客户端配置和使用示例
|
|
class ApiClient {
|
|
late final Dio _dio;
|
|
late final ApiService _apiService;
|
|
|
|
ApiClient({String? baseUrl}) {
|
|
_dio = Dio();
|
|
_setupDio();
|
|
_apiService = ApiService(_dio, baseUrl: baseUrl);
|
|
}
|
|
|
|
/// 配置 Dio
|
|
void _setupDio() {
|
|
// 基础配置
|
|
_dio.options.connectTimeout = const Duration(seconds: 30);
|
|
_dio.options.receiveTimeout = const Duration(seconds: 30);
|
|
_dio.options.sendTimeout = const Duration(seconds: 30);
|
|
|
|
// 添加拦截器
|
|
_dio.interceptors.addAll([
|
|
// 日志拦截器
|
|
LogInterceptor(
|
|
requestBody: true,
|
|
responseBody: true,
|
|
logPrint: (obj) => print(obj),
|
|
),
|
|
|
|
// 认证拦截器
|
|
BearerTokenInterceptor(token: 'your-auth-token'),
|
|
|
|
// API Key 拦截器
|
|
ApiKeyInterceptor(
|
|
apiKey: 'your-api-key',
|
|
location: ApiKeyLocation.header,
|
|
paramName: 'X-API-Key',
|
|
),
|
|
|
|
// 错误处理拦截器
|
|
ErrorHandlerInterceptor(),
|
|
]);
|
|
}
|
|
|
|
/// 获取用户信息
|
|
Future<UserResponse> getUser(int id) async {
|
|
try {
|
|
return await _apiService.getUser(id);
|
|
} catch (e) {
|
|
throw _handleError(e);
|
|
}
|
|
}
|
|
|
|
/// 创建用户
|
|
Future<UserResponse> createUser({
|
|
required String name,
|
|
required String email,
|
|
required String password,
|
|
}) async {
|
|
try {
|
|
final request = CreateUserRequest(
|
|
name: name,
|
|
email: email,
|
|
password: password,
|
|
);
|
|
return await _apiService.createUser(request);
|
|
} catch (e) {
|
|
throw _handleError(e);
|
|
}
|
|
}
|
|
|
|
/// 上传头像
|
|
Future<UploadResponse> uploadAvatar(int userId, String filePath) async {
|
|
try {
|
|
final file = await FileUploadHandler.createImageFile(filePath: filePath);
|
|
return await _apiService.uploadAvatar(userId, file);
|
|
} catch (e) {
|
|
throw _handleError(e);
|
|
}
|
|
}
|
|
|
|
/// 获取用户列表
|
|
Future<UserListResponse> getUsers({
|
|
int page = 1,
|
|
int size = 20,
|
|
String? search,
|
|
}) async {
|
|
try {
|
|
return await _apiService.getUsers(page, size, search);
|
|
} catch (e) {
|
|
throw _handleError(e);
|
|
}
|
|
}
|
|
|
|
/// 下载文件
|
|
Future<void> downloadFile(String fileId, String savePath) async {
|
|
try {
|
|
final bytes = await _apiService.downloadFile(fileId);
|
|
final file = File(savePath);
|
|
await file.writeAsBytes(bytes);
|
|
} catch (e) {
|
|
throw _handleError(e);
|
|
}
|
|
}
|
|
|
|
/// 错误处理
|
|
Exception _handleError(dynamic error) {
|
|
if (error is DioException) {
|
|
switch (error.type) {
|
|
case DioExceptionType.connectionTimeout:
|
|
case DioExceptionType.sendTimeout:
|
|
case DioExceptionType.receiveTimeout:
|
|
return TimeoutException('请求超时,请检查网络连接');
|
|
case DioExceptionType.badResponse:
|
|
final statusCode = error.response?.statusCode;
|
|
final message = error.response?.data?['message'] ?? '服务器错误';
|
|
return HttpException('HTTP $statusCode: $message');
|
|
case DioExceptionType.cancel:
|
|
return Exception('请求已取消');
|
|
case DioExceptionType.connectionError:
|
|
return Exception('网络连接错误,请检查网络设置');
|
|
default:
|
|
return Exception('未知错误: ${error.message}');
|
|
}
|
|
}
|
|
return Exception('未知错误: $error');
|
|
}
|
|
|
|
/// 释放资源
|
|
void dispose() {
|
|
_dio.close();
|
|
}
|
|
}
|
|
|
|
/// 使用示例
|
|
void main() async {
|
|
final apiClient = ApiClient(baseUrl: 'https://api.example.com/v1');
|
|
|
|
try {
|
|
// 获取用户信息
|
|
final user = await apiClient.getUser(1);
|
|
print('用户信息: ${user.name} (${user.email})');
|
|
|
|
// 创建新用户
|
|
final newUser = await apiClient.createUser(
|
|
name: 'John Doe',
|
|
email: 'john@example.com',
|
|
password: 'password123',
|
|
);
|
|
print('创建用户成功: ${newUser.id}');
|
|
|
|
// 获取用户列表
|
|
final userList = await apiClient.getUsers(page: 1, size: 10);
|
|
print('用户总数: ${userList.total}');
|
|
|
|
// 上传头像(如果有文件的话)
|
|
// final uploadResult = await apiClient.uploadAvatar(1, '/path/to/avatar.jpg');
|
|
// print('头像上传成功: ${uploadResult.url}');
|
|
|
|
// 下载文件
|
|
// await apiClient.downloadFile('file-id', '/path/to/save/file.pdf');
|
|
// print('文件下载完成');
|
|
} catch (e) {
|
|
print('API 调用失败: $e');
|
|
} finally {
|
|
apiClient.dispose();
|
|
}
|
|
}
|
|
|
|
/// 自定义异常类
|
|
class TimeoutException implements Exception {
|
|
final String message;
|
|
TimeoutException(this.message);
|
|
@override
|
|
String toString() => 'TimeoutException: $message';
|
|
}
|
|
|
|
class HttpException implements Exception {
|
|
final String message;
|
|
HttpException(this.message);
|
|
@override
|
|
String toString() => 'HttpException: $message';
|
|
}
|