Dart
复制代码
import 'package:dio/dio.dart';
import 'dart:async';
/// API异常类,用于处理网络请求中的各种错误
class ApiException implements Exception {
// 错误码
final int code;
// 错误消息
final String message;
ApiException(this.code, this.message);
@override
String toString() {
return 'ApiException: {code: $code, message: $message}';
}
// 常见的错误类型
static final networkError = ApiException(-1, '网络连接失败,请检查网络设置');
static final serverError = ApiException(500, '服务器错误,请稍后重试');
static final unauthorized = ApiException(401, '未授权,请重新登录');
static final notFound = ApiException(404, '请求的资源不存在');
}
class HttpClient {
// 单例模式
static final HttpClient _instance = HttpClient._internal();
factory HttpClient() => _instance;
late Dio _dio;
HttpClient._internal() {
// 初始化Dio
_dio = Dio();
// 配置基础选项
_dio.options = BaseOptions(
baseUrl: 'https://你的域名.com/api/',
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 10),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
);
// 添加拦截器
_dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {
// 可以在这里添加token等认证信息
// 开发环境添加详细日志
print('📤 请求URL: ${options.uri}');
print('📤 请求头: ${options.headers}');
if (options.queryParameters.isNotEmpty) {
print('📤 请求参数: ${options.queryParameters}');
}
if (options.data != null) {
print('📤 请求体: ${options.data}');
}
return handler.next(options);
},
onResponse: (response, handler) {
// 开发环境添加详细日志
print('📥 响应URL: ${response.realUri}');
print('📥 响应状态: ${response.statusCode}');
print('📥 响应数据: ${response.data}');
return handler.next(response);
},
onError: (DioException e, handler) {
// 开发环境添加详细日志
print('❌ 错误URL: ${e.requestOptions.uri}');
print('❌ 错误类型: ${e.type}');
print('❌ 错误消息: ${e.message}');
if (e.response != null) {
print('❌ 错误状态码: ${e.response?.statusCode}');
print('❌ 错误响应数据: ${e.response?.data}');
}
print('❌ 错误堆栈: ${e.stackTrace}');
return handler.next(e);
},
),
);
}
// GET请求 - 修改为支持任何类型的响应
Future<dynamic> get(
String path, {
Map<String, dynamic>? queryParameters,
}) async {
try {
Response response = await _dio.get(
path,
queryParameters: queryParameters,
);
return response.data;
} catch (e) {
throw _handleError(e);
}
}
// POST请求 - 修改为支持任何类型的响应
Future<dynamic> post(
String path, {
Map<String, dynamic>? data,
}) async {
try {
Response response = await _dio.post(path, data: data);
return response.data;
} catch (e) {
throw _handleError(e);
}
}
// PUT请求 - 修改为支持任何类型的响应
Future<dynamic> put(
String path, {
Map<String, dynamic>? data,
}) async {
try {
Response response = await _dio.put(path, data: data);
return response.data;
} catch (e) {
throw _handleError(e);
}
}
// DELETE请求 - 修改为支持任何类型的响应
Future<dynamic> delete(String path) async {
try {
Response response = await _dio.delete(path);
return response.data;
} catch (e) {
throw _handleError(e);
}
}
// 错误处理 - 抛出ApiException
dynamic _handleError(dynamic e) {
if (e is DioException) {
switch (e.type) {
case DioExceptionType.connectionTimeout:
return ApiException(408, '网络连接超时,请检查网络设置');
case DioExceptionType.sendTimeout:
return ApiException(408, '发送请求超时');
case DioExceptionType.receiveTimeout:
return ApiException(408, '接收响应超时');
case DioExceptionType.badCertificate:
return ApiException(495, '证书验证失败');
case DioExceptionType.badResponse:
// 提供更详细的错误信息
if (e.response != null) {
return ApiException(e.response?.statusCode ?? 500, '服务器错误: ${e.response?.statusMessage ?? '未知错误'}');
}
return ApiException(500, '服务器错误,请稍后重试');
case DioExceptionType.cancel:
return ApiException(0, '请求已取消');
case DioExceptionType.connectionError:
// 详细的连接错误信息
String message = '网络连接错误,请检查网络';
if (e.error != null) {
message += ' (${e.error.toString().split(':').first})';
}
return ApiException(-1, message);
case DioExceptionType.unknown:
// 尝试提供更具体的错误信息
if (e.error != null) {
String errorStr = e.error.toString();
if (errorStr.contains('SocketException')) {
return ApiException(-1, '网络连接失败,请检查网络设置');
} else if (errorStr.contains('Connection refused')) {
return ApiException(-1, '服务器连接被拒绝,请检查URL是否正确');
} else if (errorStr.contains('Failed host lookup')) {
return ApiException(-1, '域名解析失败,请检查URL是否正确');
}
}
return ApiException(-1, '未知错误,请稍后重试');
}
}
// 非Dio异常也返回具体信息
return ApiException(-1, '请求失败: ${e.toString()}');
}
}
Dart
复制代码
// GET请求方法
void getHttp() async {
try {
// 添加详细日志
print('📱 用户点击了GET请求按钮');
final response = await _httpClient.get('getHome2');
// 这里可以处理响应数据,更新UI等
try {
Map<String, dynamic> responseData;
// 检查响应类型并进行适当处理
if (response is String) {
// 将JSON字符串解析为Map对象
responseData = jsonDecode(response) as Map<String, dynamic>;
} else if (response is Map) {
responseData = response as Map<String, dynamic>;
} else if (response is List) {
return; // 如果是列表,无法按预期结构处理
} else {
return;
}
// 提取advert数据 - 根据JSON结构解析
if (responseData.containsKey('resultData') &&
responseData['resultData'] is Map) {
Map<String, dynamic> resultData =
responseData['resultData'] as Map<String, dynamic>;
if (resultData.containsKey('advert') &&
resultData['advert'] is List) {
List<dynamic> advertData = resultData['advert'] as List<dynamic>;
print('$advertData');
}
}
} catch (e) {}
// 显示成功提示
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('请求成功'), backgroundColor: Colors.green),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('请求失败'), backgroundColor: Colors.red),
);
}
}
}
Dart
复制代码
// POST请求方法 - 演示如何提交数据
void postHttp() async {
try {
// 添加详细日志
print('📱 用户点击了POST请求按钮');
// 显示加载提示
if (mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('正在提交数据...')));
}
// 准备要提交的数据
Map<String, dynamic> postData = {
'name': '测试用户',
'age': 25,
'email': 'test@example.com',
'active': true,
};
print('📤 准备提交的数据: $postData');
// 发送POST请求
// 注意:这里使用一个示例路径,实际使用时需要替换为您真实的API路径
final response = await _httpClient.post(
'examplePostEndpoint', // 替换为实际的POST接口路径
data: postData,
);
// 处理响应数据
print('📊 响应数据类型: ${response.runtimeType}');
print('📊 响应数据: $response');
// 显示成功提示
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('POST请求成功'),
backgroundColor: Colors.green,
),
);
}
} catch (e) {
print('❌ 页面层捕获POST错误: $e');
print('❌ 错误类型: ${e.runtimeType}');
// 显示错误提示
if (mounted) {
String errorMessage = 'POST请求失败';
if (e is ApiException) {
errorMessage = e.message;
} else {
errorMessage = e.toString();
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(errorMessage), backgroundColor: Colors.red),
);
}
}
}