flutter 请求封装
使用 Dio 库
安装
flutter pub add dio
创建文件
创建配置文件
class Config {
/// 连接超时时间
static const int connectTimeout = 8000;
/// 请求超时时间
static const int requestTimeout = 8000;
/// baseURL
static String getBaseUrl() {
return "xxx";
}
/// 请求日志输出
static const bool logRequest = true;
/// 默认contentType
static const String defaultContentType = "application/json";
}
创建 HttpUtil 类
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:nearhub/config/config.dart';
import 'package:nearhub/utils/device_info_util.dart';
import 'package:nearhub/utils/toast_util.dart';
/// 返回状态码
class HttpResponseCode {
static const int successCode = 0;
static const int errorCode = -1000;
static const int logoutCode = 401;
static const int connectTimeout = 6001;
static const int receiveTimeout = 6002;
}
/// http请求方法
class HttpMethod {
static const String get = "GET";
static const String post = "POST";
static const String put = "PUT";
static const String delete = "DELETE";
static const String option = "OPTION";
}
/// http请求contnettype
class HttpContentType {
static const String form = "application/x-www-form-urlencoded";
static const String formData = "multipart/form-data";
static const String json = "application/json";
static const String text = "text/xml";
}
/// 请求工具类
class HttpUtil {
static proxyRequest(Dio dio, bool proxyOn, String ipString) {
if (proxyOn) {
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.findProxy = (uri) {
// return "PROXY 192.168.1.113:8888";
return "PROXY $ipString:8888";
};
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
};
}
}
/// 获取请求头
static Future<Map<String, dynamic>> getRequestHeader({
String contentType = Config.defaultContentType,
}) async {
Map<String, dynamic> headers = {};
headers['os'] = await DeviceInfoUtil.getOs();
headers['app_version'] = await DeviceInfoUtil.getVersion();
headers['timestamp'] = DateTime.now().millisecondsSinceEpoch.toString();
headers['device'] = await DeviceInfoUtil.getDeivceName();
headers['app_store'] = DeviceInfoUtil.getChannelName();
headers['content-type'] = contentType;
headers['mac'] = '';
return headers;
}
/// 请求成功全局处理
static Response onSuccess(Response? res) {
Response successResponse = res ??
Response(
statusCode: HttpResponseCode.errorCode,
requestOptions: RequestOptions(path: ""));
return successResponse;
}
/// 请求失败全局处理
static Response onError(DioError error) {
// 请求错误处理
Response errorResponse = error.response ??
Response(
statusCode: HttpResponseCode.errorCode,
requestOptions: RequestOptions(path: ""));
switch (error.type) {
case DioErrorType.connectTimeout: // 请求超时
errorResponse.statusCode = HttpResponseCode.connectTimeout;
errorResponse.statusMessage = "网络连接超时,请检查网络";
break;
case DioErrorType.receiveTimeout: // 请求连接超时
errorResponse.statusCode = HttpResponseCode.receiveTimeout;
errorResponse.statusMessage = "网络请求超时,请稍后重试";
break;
case DioErrorType.response: // 服务器内部错误
errorResponse.statusCode = error.response?.statusCode;
errorResponse.statusMessage = "服务器繁忙,请稍后重试";
break;
case DioErrorType.cancel: // 请求取消
errorResponse.statusCode = error.response?.statusCode;
errorResponse.statusMessage = "请求取消";
break;
case DioErrorType.other: // 其他错误
errorResponse.statusCode = error.response?.statusCode;
errorResponse.statusMessage = "网络错误,请稍后重试";
break;
default:
}
/// 添加错误提示
ToastUtil.error(errorResponse.statusMessage ?? "");
/// 返回错误
return errorResponse;
}
}
创建 HttpRequest 类
import 'package:dio/dio.dart';
import 'package:nearhub/api/custom_interceptor.dart';
import 'package:nearhub/config/config.dart';
import 'package:nearhub/utils/http_util.dart';
import 'package:nearhub/utils/toast_util.dart';
class HttpRequest {
static late HttpRequest _instance;
static bool _isInstanceCreated = false;
static Dio? _dio;
factory HttpRequest() => getInstance();
static HttpRequest get instance => getInstance();
static HttpRequest getInstance() {
if (_isInstanceCreated == false) {
_instance = HttpRequest._internal();
}
_isInstanceCreated = true;
return _instance;
}
HttpRequest._internal() {
if (_isInstanceCreated == false) {
var options = BaseOptions(
baseUrl: Config.getBaseUrl(),
connectTimeout: Config.connectTimeout,
receiveTimeout: Config.requestTimeout,
);
_dio = Dio(options);
/// 加载拦截器
_dio?.interceptors.add(CustomInterceptor());
}
}
/// get请求
Future<Response> get(
String path, {
Map<String, dynamic>? params,
bool? loading = false,
String? contentType = Config.defaultContentType,
Function(Response res)? onSuccess,
Function(Response errRes)? onError,
}) async {
return request(path, HttpMethod.get,
params: params,
loading: loading,
contentType: contentType,
onError: onError,
onSuccess: onSuccess);
}
/// post请求
Future<Response> post(
String path, {
Map<String, dynamic>? params,
Map<String, dynamic>? data,
bool? loading = false,
String? contentType = Config.defaultContentType,
Function(Response res)? onSuccess,
Function(Response errRes)? onError,
}) async {
return request(path, HttpMethod.post,
params: params,
data: data,
loading: loading,
contentType: contentType,
onError: onError,
onSuccess: onSuccess);
}
/// put请求
Future<Response> put(
String path, {
Map<String, dynamic>? params,
Map<String, dynamic>? data,
bool? loading = false,
String? contentType = Config.defaultContentType,
Function(Response res)? onSuccess,
Function(Response errRes)? onError,
}) async {
return request(path, HttpMethod.put,
params: params,
data: data,
loading: loading,
contentType: contentType,
onError: onError,
onSuccess: onSuccess);
}
/// delete请求
Future<Response> delete(
String path, {
Map<String, dynamic>? params,
Map<String, dynamic>? data,
bool? loading = false,
String? contentType = Config.defaultContentType,
Function(Response res)? onSuccess,
Function(Response errRes)? onError,
}) async {
return request(path, HttpMethod.delete,
params: params,
data: data,
loading: loading,
contentType: contentType,
onError: onError,
onSuccess: onSuccess);
}
/// option请求
Future<Response> option(
String path, {
Map<String, dynamic>? params,
Map<String, dynamic>? data,
bool? loading = false,
String? contentType = Config.defaultContentType,
Function(Response res)? onSuccess,
Function(Response errRes)? onError,
}) async {
return request(path, HttpMethod.option,
params: params,
loading: loading,
contentType: contentType,
onError: onError,
onSuccess: onSuccess);
}
Future<Response> request(
String path,
String method, {
Map<String, dynamic>? data,
Map<String, dynamic>? params,
String? contentType = Config.defaultContentType,
bool? loading = false,
Function(Response res)? onSuccess,
Function(Response errRes)? onError,
}) async {
_dio!.options.method = method;
_dio!.options.headers['content-type'] = contentType;
Response response = Response(
statusCode: HttpResponseCode.errorCode,
requestOptions: RequestOptions(path: path));
if (loading == true) {
ToastUtil.show();
}
try {
response = await _dio?.request(
path,
queryParameters: params,
data: data,
) ??
response;
onSuccess?.call(response);
} catch (e) {
DioError err = DioError(
requestOptions: RequestOptions(
path: path, method: method, queryParameters: params, data: data),
response: response,
type: DioErrorType.response,
);
if (e is DioError) {
err.type = e.type;
}
response.statusCode = err.response?.statusCode;
response.data = err.response?.data;
response.statusMessage = err.message;
onError?.call(response);
}
ToastUtil.dismiss();
return response;
}
}
创建 自定义拦截类
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:nearhub/config/config.dart';
import 'package:nearhub/utils/c_log_util.dart';
import 'package:nearhub/utils/http_util.dart';
class CustomInterceptor extends Interceptor {
@override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
/// 加载请求头
Map<String, dynamic> headers = await HttpUtil.getRequestHeader();
options.headers = headers;
if (Config.logRequest) {
LOG.d('');
LOG.d('[=========== ${options.path} ==========]');
LOG.d('[ URL ]:${options.baseUrl + options.path}');
LOG.d('[ METHOD ]:${options.method}');
LOG.d('[ HEADER ]:${json.encode(options.headers)}');
LOG.d('[ PARAMS ]:${json.encode(options.queryParameters)}');
LOG.d('[ DATAS ]:${json.encode(options.data)}');
}
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
/// 可以在此处处理加密
if (Config.logRequest) {
LOG.d('[ SUCCESS ]');
LOG.d('[ RESULT ]:${json.encode(response.data)}');
LOG.d('[========================================]');
LOG.d('');
}
/// 公共处理成功请求
HttpUtil.onSuccess(response);
handler.next(response);
}
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
if (Config.logRequest) {
LOG.d('[ *ERROR* ]');
LOG.d('[ ERROR ]:${json.encode(err)}');
LOG.d('[========================================]');
LOG.d('');
}
/// 公共处理失败请求
HttpUtil.onError(err);
handler.next(err);
}
}
使用
Response login = await HttpRequest.instance.post("/user/login", data: {
"username": "2185675739@qq.com",
"password": "ywh1996",
}, contentType: HttpContentType.form);
LOG.d(login.toString());