Flutter 开发中,常用的网络请求库为 Dio。本文对 Dio 进行简单封装。
base_res.dart
import 'package:dio/dio.dart';
class BaseResponse {
// 通用参数,可根据实际业务修改
late int code;
late String message;
late dynamic data;
// 业务请求是否成功
late bool success;
// Dio 返回的原始 Response 数据
Response? ores;
BaseResponse({
required this.code,
required this.message,
required this.data,
required this.success,
required this.ores,
});
BaseResponse.fromJson(dynamic json) {
code = json?['code'] ?? -1;
message = json?['message'] ?? '';
data = json?['data'] ?? '';
success = code == 0 ? true : false;
}
}
api.dart
import 'package:flutter/foundation.dart';
class Api {
static const baseUrl = kDebugMode ? '' : '';
// login
static const loginUrl = '';
}
dio_intercept.dart
import 'package:dio/dio.dart';
class AuthInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
// 此处根据业务逻辑,自行判断处理
if ('token' != '') {
options.headers['token'] = 'token';
}
super.onRequest(options, handler);
}
}
class LogInterceptor extends Interceptor {
late DateTime _startTime;
late DateTime _endTime;
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
_startTime = DateTime.now();
// 此处根据业务逻辑,自行增加 requestUrl requestMethod headers queryParameters 等参数的打印
print('---Request Start---');
super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
_endTime = DateTime.now();
final int duration = _endTime.difference(_startTime).inMilliseconds;
print('---Request End: 耗时 $duration 毫秒---');
super.onResponse(response, handler);
}
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
print('---Resuest Error: ${err.toString()}');
super.onError(err, handler);
}
}
dio_utils.dart
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_application_dio/net/api.dart';
import 'package:flutter_application_dio/net/base_res.dart';
import 'package:flutter_application_dio/net/dio_intercept.dart' as interceptor;
import 'package:flutter_application_dio/net/dio_wrap.dart';
class HttpUtils {
static final HttpUtils _instance = HttpUtils._();
static HttpUtils get instance => HttpUtils();
factory HttpUtils() => _instance;
static late Dio _dio;
Dio get dio => _dio;
HttpUtils._() {
// 构造 Dio options
final BaseOptions options = BaseOptions(
connectTimeout: 15000,
receiveTimeout: 15000,
sendTimeout: 10000,
responseType: ResponseType.plain,
validateStatus: (_) => true,
baseUrl: Api.baseUrl,
);
// 实例化 Dio
_dio = Dio(options);
// 忽略 https 证书校验
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
return client;
};
// 添加迭代器
_dio.interceptors.add(interceptor.AuthInterceptor());
if (kDebugMode) {
_dio.interceptors.add(interceptor.LogInterceptor());
}
}
Future _request(
String url, {
String? method = 'POST',
dynamic params,
bool tips = false,
void Function(int, int)? onSendProgress,
void Function(int, int)? onReceiveProgress,
}) async {
late BaseResponse response;
try {
if (tips) {
// 展示 loading
}
late Response res;
if (method == 'GET') {
res = await _dio.get(url, queryParameters: params);
} else if (method == 'UPLOAD') {
FormData formData = FormData.fromMap(params);
res = await _dio.post(
url,
data: formData,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
} else {
res = await _dio.post(
url,
data: params,
);
}
response = DioWrapper.responseWrapper(res);
} catch (e) {
response = DioWrapper.errorWrapper(e);
} finally {
// 隐藏 loading
}
return response;
}
// GET
Future get(
String url, {
dynamic params,
bool tips = false,
}) async {
return _request(
url,
method: 'GET',
params: params,
tips: tips,
);
}
// POST
Future post(
String url, {
dynamic params,
bool tips = false,
}) async {
return _request(
url,
method: 'POST',
params: params,
tips: tips,
);
}
// UPLOAD
Future upload(
String url, {
dynamic params,
bool tips = false,
void Function(int, int)? onSendProgress,
void Function(int, int)? onReceiveProgress,
}) async {
return _request(
url,
method: 'UPLOAD',
params: params,
tips: tips,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
}
dio_wrapper.dart
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter_application_dio/net/base_res.dart';
class DioWrapper {
static BaseResponse errorWrapper(Object e) {
return BaseResponse(
code: -1,
message: e is DioError ? _dioErrorWrapper(e) : '未知错误',
data: '',
success: false,
ores: null,
);
}
static String _dioErrorWrapper(DioError error) {
switch (error.type) {
case DioErrorType.connectTimeout:
return '连接服务器超时';
case DioErrorType.sendTimeout:
return '连接服务器超时';
case DioErrorType.receiveTimeout:
return '连接服务器超时';
case DioErrorType.cancel:
return '连接被取消';
default:
return '未知错误';
}
}
static BaseResponse responseWrapper(Response response) {
// 此处如果数据比较大,可以使用 compute 放在后台计算
final res = jsonDecode(response.data);
if (response.statusCode == 200) {
final BaseResponse wrapres = BaseResponse.fromJson(res);
wrapres.ores = response;
return wrapres;
} else {
var msg = res["error_description"] ?? '';
if (response.statusCode == 401) {
msg = 'token失效';
}
return BaseResponse(
code: -1,
success: false,
message: msg,
data: "",
ores: response,
);
}
}
}
void login() async {
final res = await HttpUtils.instance.post(
Api.loginUrl,
params: {},
tips: true,
);
print(res);
}