DioMixin(Dio实现类)
abstract class DioMixin implements Dio {
/// Default Request config. More see [BaseOptions].
@override
late BaseOptions options;
/// Each Dio instance has a interceptor by which you can intercept requests or responses before they are
/// handled by `then` or `catchError`. the [interceptor] field
/// contains a [RequestInterceptor] and a [ResponseInterceptor] instance.
final Interceptors _interceptors = Interceptors();
@override
Interceptors get interceptors => _interceptors;
@override
late HttpClientAdapter httpClientAdapter;
@override
Transformer transformer = BackgroundTransformer();
bool _closed = false;
}
用作其他类继承或混合的基类。
下面是DioMixin类的主要属性和方法:
options:默认的请求配置,类型为BaseOptions,用于设置请求的默认参数,如请求超时时间、请求头等。interceptors:拦截器,类型为Interceptors,用于拦截请求和响应,并进行相应的处理。通过拦截器,可以在请求或响应被处理之前进行自定义操作。httpClientAdapter:HTTP客户端适配器,用于发送HTTP请求。具体的实现可以根据需要进行配置。transformer:数据转换器,用于对请求和响应的数据进行转换。默认使用BackgroundTransformer,可以自定义实现其他的转换器。_closed:表示Dio实例是否已关闭的标志。当调用close方法关闭Dio实例时,该标志会被设置为true。
DioMixin类提供了一些默认的属性和方法实现,方便其他类进行扩展和定制。通过继承或混合DioMixin类,可以快速构建自定义的Dio实例,并使用其中的属性和方法来发送HTTP请求。
close
void close({bool force = false}) {
_closed = true;
httpClientAdapter.close(force: force);
}
close方法是DioMixin类中的一个方法,用于关闭Dio实例。
下面是close方法的作用:
- 将
_closed属性设置为true,表示Dio实例已关闭。 - 调用
httpClientAdapter的close方法来关闭底层的HTTP客户端适配器。
参数说明:
force(可选):是否强制关闭,默认为false。当设置为true时,会立即关闭所有活动的连接以释放所有资源;当设置为false时,会等待所有活动的连接完成后再关闭。
通过调用close方法,可以关闭Dio实例并释放相关资源,确保在不再需要使用Dio实例时进行清理操作。
get
Future<Response<T>> get<T>(String path, {
Map<String, dynamic>? queryParameters,
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
}) {
return request<T>(
path,
data: data,
queryParameters: queryParameters,
options: checkOptions('GET', options),
onReceiveProgress: onReceiveProgress,
cancelToken: cancelToken,
);
}
get方法是DioMixin类中的一个方法,用于发送HTTP GET请求。
下面是get方法的作用:
- 使用
request方法发送HTTP GET请求,传递相应的参数。 - 参数
path表示请求的URL路径。 - 参数
queryParameters(可选)表示请求的查询参数。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onReceiveProgress(可选)表示接收进度的回调函数。
通过调用get方法,可以方便地发送HTTP GET请求,并返回对应的Future<Response>对象,用于处理响应结果。
getUri
Future<Response<T>> getUri<T>(Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
}) {
return requestUri<T>(
uri,
data: data,
options: checkOptions('GET', options),
onReceiveProgress: onReceiveProgress,
cancelToken: cancelToken,
);
}
getUri方法是DioMixin类中的一个方法,用于发送HTTP GET请求。
下面是getUri方法的作用:
- 使用
requestUri方法发送HTTP GET请求,传递相应的参数。 - 参数
uri表示请求的完整URI。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onReceiveProgress(可选)表示接收进度的回调函数。
通过调用getUri方法,可以方便地发送HTTP GET请求,并返回对应的Future<Response>对象,用于处理响应结果。
post
Future<Response<T>> post<T>(String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return request<T>(
path,
data: data,
options: checkOptions('POST', options),
queryParameters: queryParameters,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
post方法是DioMixin类中的一个方法,用于发送HTTP POST请求。
下面是post方法的作用:
- 使用
request方法发送HTTP POST请求,传递相应的参数。 - 参数
path表示请求的路径。 - 参数
data(可选)表示请求的数据。 - 参数
queryParameters(可选)表示请求的查询参数。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onSendProgress(可选)表示发送进度的回调函数。 - 参数
onReceiveProgress(可选)表示接收进度的回调函数。
通过调用post方法,可以方便地发送HTTP POST请求,并返回对应的Future<Response>对象,用于处理响应结果。
postUri
Future<Response<T>> postUri<T>(Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return requestUri<T>(
uri,
data: data,
options: checkOptions('POST', options),
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
postUri方法是DioMixin类中的一个方法,用于发送HTTP POST请求。
下面是postUri方法的作用:
- 使用
requestUri方法发送HTTP POST请求,传递相应的参数。 - 参数
uri表示请求的URI。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onSendProgress(可选)表示发送进度的回调函数。 - 参数
onReceiveProgress(可选)表示接收进度的回调函数。
通过调用postUri方法,可以方便地发送HTTP POST请求,并返回对应的Future<Response>对象,用于处理响应结果。
put
Future<Response<T>> put<T>(String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return request<T>(
path,
data: data,
queryParameters: queryParameters,
options: checkOptions('PUT', options),
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
put方法是DioMixin类中的一个方法,用于发送HTTP PUT请求。
下面是put方法的作用:
- 使用
request方法发送HTTP PUT请求,传递相应的参数。 - 参数
path表示请求的路径。 - 参数
data(可选)表示请求的数据。 - 参数
queryParameters(可选)表示请求的查询参数。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onSendProgress(可选)表示发送进度的回调函数。 - 参数
onReceiveProgress(可选)表示接收进度的回调函数。
通过调用put方法,可以方便地发送HTTP PUT请求,并返回对应的Future<Response>对象,用于处理响应结果。
putUri
Future<Response<T>> putUri<T>(Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return requestUri<T>(
uri,
data: data,
options: checkOptions('PUT', options),
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
putUri方法是DioMixin类中的一个方法,用于发送HTTP PUT请求。
下面是putUri方法的作用:
- 使用
requestUri方法发送HTTP PUT请求,传递相应的参数。 - 参数
uri表示请求的完整URI。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onSendProgress(可选)表示发送进度的回调函数。 - 参数
onReceiveProgress(可选)表示接收进度的回调函数。
通过调用putUri方法,可以方便地发送HTTP PUT请求,并返回对应的Future<Response>对象,用于处理响应结果。
head
Future<Response<T>> head<T>(String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
}) {
return request<T>(
path,
data: data,
queryParameters: queryParameters,
options: checkOptions('HEAD', options),
cancelToken: cancelToken,
);
}
head方法是DioMixin类中的一个方法,用于发送HTTP HEAD请求。
下面是head方法的作用:
- 使用
request方法发送HTTP HEAD请求,传递相应的参数。 - 参数
path表示请求的路径。 - 参数
data(可选)表示请求的数据。 - 参数
queryParameters(可选)表示请求的查询参数。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。
通过调用head方法,可以方便地发送HTTP HEAD请求,并返回对应的Future<Response>对象,用于处理响应结果。
headUri
Future<Response<T>> headUri<T>(Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
}) {
return requestUri<T>(
uri,
data: data,
options: checkOptions('HEAD', options),
cancelToken: cancelToken,
);
}
headUri方法是DioMixin类中的一个方法,用于发送HTTP HEAD请求,并通过URI参数指定请求的URL。
下面是headUri方法的作用:
- 使用
requestUri方法发送HTTP HEAD请求,传递相应的参数。 - 参数
uri表示请求的URI,用于指定请求的URL。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。
通过调用headUri方法,可以方便地发送HTTP HEAD请求,并返回对应的Future<Response>对象,用于处理响应结果。
delete
Future<Response<T>> delete<T>(String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
}) {
return request<T>(
path,
data: data,
queryParameters: queryParameters,
options: checkOptions('DELETE', options),
cancelToken: cancelToken,
);
}
delete方法是DioMixin类中的一个方法,用于发送HTTP DELETE请求。
下面是delete方法的作用:
- 使用
request方法发送HTTP DELETE请求,传递相应的参数。 - 参数
path表示请求的路径,用于指定请求的URL。 - 参数
data(可选)表示请求的数据。 - 参数
queryParameters(可选)表示请求的查询参数。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。
通过调用delete方法,可以方便地发送HTTP DELETE请求,并返回对应的Future<Response>对象,用于处理响应结果。
deleteUri
Future<Response<T>> deleteUri<T>(Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
}) {
return requestUri<T>(
uri,
data: data,
options: checkOptions('DELETE', options),
cancelToken: cancelToken,
);
}
deleteUri方法是DioMixin类中的一个方法,用于发送HTTP DELETE请求。
下面是deleteUri方法的作用:
- 使用
requestUri方法发送HTTP DELETE请求,传递相应的参数。 - 参数
uri表示请求的完整URI,用于指定请求的URL。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。
通过调用deleteUri方法,可以方便地发送HTTP DELETE请求,并返回对应的Future<Response>对象,用于处理响应结果。
patch
Future<Response<T>> patch<T>(String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return request<T>(
path,
data: data,
queryParameters: queryParameters,
options: checkOptions('PATCH', options),
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
patch方法是DioMixin类中的一个方法,用于发送HTTP PATCH请求。
下面是patch方法的作用:
- 使用
request方法发送HTTP PATCH请求,传递相应的参数。 - 参数
path表示请求的路径,用于指定请求的URL路径。 - 参数
data(可选)表示请求的数据。 - 参数
queryParameters(可选)表示请求的查询参数。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onSendProgress(可选)表示请求发送进度的回调函数。 - 参数
onReceiveProgress(可选)表示请求接收进度的回调函数。
通过调用patch方法,可以方便地发送HTTP PATCH请求,并返回对应的Future<Response>对象,用于处理响应结果。
patchUri
Future<Response<T>> patchUri<T>(Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return requestUri<T>(
uri,
data: data,
options: checkOptions('PATCH', options),
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
patchUri方法是DioMixin类中的一个方法,用于发送HTTP PATCH请求。
下面是patchUri方法的作用:
- 使用
requestUri方法发送HTTP PATCH请求,传递相应的参数。 - 参数
uri表示请求的完整URI,用于指定请求的URL。 - 参数
data(可选)表示请求的数据。 - 参数
options(可选)表示请求的配置选项。 - 参数
cancelToken(可选)表示用于取消请求的CancelToken实例。 - 参数
onSendProgress(可选)表示请求发送进度的回调函数。 - 参数
onReceiveProgress(可选)表示请求接收进度的回调函数。
通过调用patchUri方法,可以方便地发送HTTP PATCH请求,并返回对应的Future<Response>对象,用于处理响应结果。
downloadUri
Future<Response> downloadUri(Uri uri,
dynamic savePath, {
ProgressCallback? onReceiveProgress,
CancelToken? cancelToken,
bool deleteOnError = true,
String lengthHeader = Headers.contentLengthHeader,
Object? data,
Options? options,
}) {
return download(
uri.toString(),
savePath,
onReceiveProgress: onReceiveProgress,
lengthHeader: lengthHeader,
deleteOnError: deleteOnError,
cancelToken: cancelToken,
data: data,
options: options,
);
}
downloadUri方法是DioMixin类中的一个方法,用于从指定的URI下载文件。
下面是downloadUri方法的作用:
- 使用
download方法下载文件,传递相应的参数。 - 参数
uri表示下载文件的URI,用于指定文件的URL。 - 参数
savePath表示下载文件保存的路径。 - 参数
onReceiveProgress(可选)表示下载进度的回调函数。 - 参数
cancelToken(可选)表示用于取消下载的CancelToken实例。 - 参数
deleteOnError(可选)表示是否在下载发生错误时删除已下载的文件,默认为true。 - 参数
lengthHeader(可选)表示用于获取文件长度的HTTP头字段,默认为Headers.contentLengthHeader。 - 参数
data(可选)表示下载请求的数据。 - 参数
options(可选)表示下载请求的配置选项。
通过调用downloadUri方法,可以方便地从指定的URI下载文件,并返回对应的Future<Response>对象,用于处理下载结果。
download
Future<Response> download(String urlPath,
dynamic savePath, {
ProgressCallback? onReceiveProgress,
Map<String, dynamic>? queryParameters,
CancelToken? cancelToken,
bool deleteOnError = true,
String lengthHeader = Headers.contentLengthHeader,
Object? data,
Options? options,
}) {
throw UnsupportedError(
'download() is not available in the current environment.',
);
}
这个download方法是在DioMixin类中定义的,用于在特定环境中下载文件。
这个方法抛出了一个UnsupportedError异常,表示在当前环境中不支持下载操作。可能是因为当前环境没有提供相应的下载功能或者相关的依赖库未安装。
如果你想在当前环境中实现下载功能,你可以自行编写适合当前环境的下载方法,或者使用其他支持下载的库。
requestUri
Future<Response<T>> requestUri<T>(Uri uri, {
Object? data,
CancelToken? cancelToken,
Options? options,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return request(
uri.toString(),
data: data,
cancelToken: cancelToken,
options: options,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
requestUri 方法是一个用于发送 HTTP 请求的便捷方法,它会将传入的 Uri 对象转换为字符串,并调用 request 方法来发送请求。
在 requestUri 方法中,你可以指定要发送的请求的 Uri、请求数据、取消令牌、请求选项以及发送和接收进度回调。它会将这些参数转发给 request 方法来执行实际的请求。
如果你想要使用 requestUri 方法发送请求,你可以提供一个 Uri 对象,以及其他可选的参数。然后,requestUri 方法将使用 uri.toString() 将 Uri 对象转换为字符串,并将其传递给 request 方法来发送请求。
请注意,requestUri 方法返回一个 Future<Response<T>> 对象,该对象表示发送请求后的响应。你可以使用 await 关键字等待响应的到达,或者使用 .then 和 .catchError 方法处理响应。
request
Future<Response<T>> request<T>(String path, {
Object? data,
Map<String, dynamic>? queryParameters,
CancelToken? cancelToken,
Options? options,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
final requestOptions = (options ?? Options()).compose(
this.options,
path,
data: data,
queryParameters: queryParameters,
onReceiveProgress: onReceiveProgress,
onSendProgress: onSendProgress,
cancelToken: cancelToken,
sourceStackTrace: StackTrace.current,
);
if (_closed) {
throw DioError.connectionError(
reason: "Dio can't establish a new connection after it was closed.",
requestOptions: requestOptions,
);
}
return fetch<T>(requestOptions);
}
request 方法是一个用于发送 HTTP 请求的便捷方法。它接受一个路径(path)参数,以及其他可选的参数,如请求数据(data)、查询参数(queryParameters)、取消令牌(cancelToken)、请求选项(options)以及发送和接收进度回调。
在 request 方法中,首先使用传入的参数构建了一个 RequestOptions 对象,用于描述请求的各种选项和配置。这里使用了 compose 方法,它会将传入的参数与 Dio 实例的默认选项进行合并,生成最终的请求选项。
然后,检查 _closed 属性来确定 Dio 实例是否已关闭。如果已关闭,则抛出一个 DioError 异常,指示无法在关闭后建立新的连接。
最后,调用 fetch<T> 方法,将构建的 requestOptions 作为参数,发送实际的请求,并返回一个 Future<Response<T>> 对象,表示发送请求后的响应。
如果你想要使用 request 方法发送请求,你可以提供一个路径(path)以及其他可选的参数。request 方法将使用这些参数构建请求选项,并发送请求。注意,你也可以通过修改默认选项 options 来自定义请求的行为。
请注意,request 方法是一个异步方法,返回一个 Future 对象,你可以使用 await 关键字等待响应的到达,或者使用 .then 和 .catchError 方法处理响应。
fetch
抓取网络请求数据
requestInterceptorWrapper
Future<Response<T>> fetch<T>(RequestOptions requestOptions) async {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||
requestOptions.responseType == ResponseType.stream)) {
if (T == String) {
requestOptions.responseType = ResponseType.plain;
} else {
requestOptions.responseType = ResponseType.json;
}
}
// Convert the request interceptor to a functional callback in which
// we can handle the return value of interceptor callback.
以下代码中,`requestInterceptorWrapper`函数的返回类型是`FutureOr Function(dynamic)`,它定义了一个接受`dynamic`类型参数的函数,并返回`FutureOr`类型的结果。
FutureOr Function(dynamic) requestInterceptorWrapper(InterceptorSendCallback interceptor,) {
return (dynamic incomingState) async {
final state = incomingState as InterceptorState;
if (state.type == InterceptorResultType.next) {
return listenCancelForAsyncTask(
requestOptions.cancelToken,
Future(() {
final requestHandler = RequestInterceptorHandler();
interceptor(state.data as RequestOptions, requestHandler);
return requestHandler.future;
}),
);
} else {
return state;
}
};
}
}
这段代码定义了一个函数 requestInterceptorWrapper,它将一个拦截器回调函数 interceptor 包装成另一个函数。这个包装后的函数接收一个动态类型的参数 incomingState,并返回一个 FutureOr 对象。
具体解释如下:
-
incomingState被强制转换为InterceptorState类型,并赋值给变量state。 -
如果
state的type属性等于InterceptorResultType.next,则执行下面的代码块。- 调用
listenCancelForAsyncTask函数,传递requestOptions.cancelToken和一个Future对象。 - 在
Future对象中创建一个RequestInterceptorHandler实例requestHandler。 - 调用拦截器回调函数
interceptor,传递state.data(强制转换为RequestOptions类型)和requestHandler。 - 返回
requestHandler.future,即一个Future对象。
- 调用
-
如果
state的type属性不等于InterceptorResultType.next,则直接返回state对象。
这行代码的作用是将拦截器回调函数 interceptor 包装成一个能够处理异步任务的函数,并根据 state 的类型进行不同的处理。如果 state 的类型为 InterceptorResultType.next,则执行拦截器回调函数,并将返回的结果包装在一个 Future 中;否则,直接返回 state 对象。
_requestInterceptorWrapper
FutureOr _requestInterceptorWrapper() {
return Future.value(2);
}
这段代码定义了一个函数 _requestInterceptorWrapper,它返回一个 FutureOr 对象。
具体解释如下:
_requestInterceptorWrapper函数没有参数。- 在函数体内部,使用
Future.value(2)创建一个已完成的Future对象,其值为 2。 - 返回这个已完成的
Future对象作为FutureOr对象。
这行代码的作用是创建一个已完成的 Future 对象,并将其作为 FutureOr 对象返回。这个已完成的 Future 对象的值是 2。
responseInterceptorWrapper
FutureOr<dynamic> Function(dynamic) responseInterceptorWrapper(InterceptorSuccessCallback interceptor,) {
return (dynamic incomingState) async {
final state = incomingState as InterceptorState;
if (state.type == InterceptorResultType.next || state.type == InterceptorResultType.resolveCallFollowing) {
return listenCancelForAsyncTask(
requestOptions.cancelToken,
Future(() {
final responseHandler = ResponseInterceptorHandler();
interceptor(state.data as Response, responseHandler);
return responseHandler.future;
}),
);
} else {
return state;
}
};
}
这段代码定义了一个函数 responseInterceptorWrapper,它接受一个参数 interceptor,类型为 InterceptorSuccessCallback,并返回一个 FutureOr<dynamic> Function(dynamic) 对象。
具体解释如下:
-
responseInterceptorWrapper函数接受一个回调函数interceptor,该回调函数的类型为InterceptorSuccessCallback。 -
在函数体内部,定义了一个异步函数,接受一个参数
incomingState,类型为dynamic。 -
在异步函数体内部,首先将
incomingState强制转换为InterceptorState类型,并将其赋值给变量state。 -
接下来,通过检查
state的type属性,判断执行不同的逻辑。-
如果
state.type的值为InterceptorResultType.next或InterceptorResultType.resolveCallFollowing,表示需要执行成功的拦截器回调函数。- 在这种情况下,调用
listenCancelForAsyncTask方法,传递requestOptions.cancelToken和一个异步函数作为参数。 - 在异步函数体内,首先创建一个
ResponseInterceptorHandler对象,并将state.data(类型为Response)和该处理器对象传递给拦截器回调函数interceptor。 - 返回
responseHandler.future,即一个Future对象,该对象在处理器对象中的future属性被解析时完成。
- 在这种情况下,调用
-
如果
state.type的值不是上述两种情况,则直接返回state。
-
这行代码的作用是创建一个函数 responseInterceptorWrapper,该函数接受一个拦截器回调函数作为参数,并根据传入的状态类型执行相应的逻辑。如果状态类型符合条件,则调用拦截器回调函数并返回相应的 Future 对象,否则直接返回状态对象。返回的函数可以用作请求流程中的响应拦截器
errorInterceptorWrapper
FutureOr<dynamic> Function(Object) errorInterceptorWrapper(InterceptorErrorCallback interceptor,) {
return (err) {
final state = err is InterceptorState ? err : InterceptorState(assureDioError(err, requestOptions));
Future<InterceptorState> handleError() async {
final errorHandler = ErrorInterceptorHandler();
interceptor(state.data, errorHandler);
return errorHandler.future;
}
// The request has already been canceled,
// there is no need to listen for another cancellation.
if (state.data is DioError && state.data.type == DioErrorType.cancel) {
return handleError();
} else if (state.type == InterceptorResultType.next ||
state.type == InterceptorResultType.rejectCallFollowing) {
return listenCancelForAsyncTask(
requestOptions.cancelToken,
Future(handleError),
);
} else {
throw err;
}
};
}
这段代码定义了一个函数 errorInterceptorWrapper,它接受一个参数 interceptor,类型为 InterceptorErrorCallback,并返回一个 FutureOr<dynamic> Function(Object) 对象。
具体解释如下:
-
errorInterceptorWrapper函数接受一个回调函数interceptor,该回调函数的类型为InterceptorErrorCallback。 -
在函数体内部,定义了一个匿名函数,接受一个参数
err,类型为Object。 -
在匿名函数体内部,首先判断
err是否为InterceptorState类型,如果是,则将err赋值给变量state;如果不是,则通过assureDioError方法将err和requestOptions转换为InterceptorState类型,并将结果赋值给变量state。 -
接下来,定义了一个异步函数
handleError,用于处理错误。 -
在异步函数体内部,首先创建一个
ErrorInterceptorHandler对象,并将state.data和该处理器对象传递给拦截器回调函数interceptor。 -
根据不同的条件进行处理:
-
如果
state.data是DioError类型且其type属性为DioErrorType.cancel,表示请求已被取消,不需要再监听其他取消操作。此时调用handleError函数处理错误。 -
如果
state.type的值为InterceptorResultType.next或InterceptorResultType.rejectCallFollowing,表示需要执行拒绝的拦截器回调函数。- 在这种情况下,调用
listenCancelForAsyncTask方法,传递requestOptions.cancelToken和一个异步函数handleError作为参数。
- 在这种情况下,调用
-
如果上述条件都不满足,则抛出原始错误
err。
-
-
返回的函数可以用作请求流程中的错误处理器。
这段代码的作用是创建一个函数 errorInterceptorWrapper,该函数接受一个拦截器回调函数作为参数,并根据传入的错误状态类型执行相应的逻辑。根据错误状态的不同,可能会调用拦截器回调函数进行处理或抛出错误。返回的函数可以用作请求流程中的错误处理器。
future
// Build a request flow in which the processors(interceptors)
// execute in FIFO order.
// Start the request flow
Future<dynamic> future = Future<dynamic>(() => InterceptorState(requestOptions));
这段代码构建了一个请求流程,其中处理器(拦截器)按照先进先出(FIFO)的顺序执行。
具体解释如下:
- 首先,使用
Future<dynamic>构造了一个future对象,并将其初始化为一个立即执行的Future。 Future<dynamic>(() => InterceptorState(requestOptions))表达式中的箭头函数() => InterceptorState(requestOptions)用于创建一个初始的InterceptorState对象,并作为Future的返回值。- 这个初始的
InterceptorState对象包含了请求的配置信息requestOptions。 - 这个
future对象标志着请求流程的开始。
接下来的代码会在这个初始的 future 对象的基础上继续构建请求流程,依次添加请求拦截器、请求派发、响应拦截器和错误处理器。每个处理器都会按照先进先出的顺序执行,并根据需要对请求或响应进行处理。最终,请求流程的结果将被返回。
Add request interceptors to request flow
// Add request interceptors to request flow
for (final interceptor in interceptors) {
final fun = interceptor is QueuedInterceptor ? interceptor._handleRequest : interceptor.onRequest;
future = future.then(requestInterceptorWrapper(fun));
}
// Add dispatching callback to request flow
future = future.then(
requestInterceptorWrapper((RequestOptions reqOpt,
RequestInterceptorHandler handler,) {
requestOptions = reqOpt;
_dispatchRequest<T>(reqOpt).then((value) => handler.resolve(value, true)).catchError((e) {
handler.reject(e as DioError, true);
});
}),
);
这段代码向请求流程中添加了请求拦截器,并在最后添加了一个派发请求的回调函数。
具体解释如下:
- 首先,通过
for循环遍历interceptors列表,其中的每个元素都是一个请求拦截器。 - 对于每个拦截器,使用条件判断
interceptor is QueuedInterceptor来确定使用不同的处理函数。如果是QueuedInterceptor类型的拦截器,则使用_handleRequest函数,否则使用onRequest函数。将相应的处理函数赋值给变量fun。 - 然后,通过
future.then(requestInterceptorWrapper(fun))将处理函数包装成一个回调函数,并将其添加到请求流程中。requestInterceptorWrapper函数用于包装拦截器的处理函数,使其能够在异步任务中执行,并处理回调结果。 - 循环结束后,请求流程中已经添加了所有的请求拦截器。
接下来,通过 future.then(...) 添加了一个派发请求的回调函数到请求流程中。该回调函数使用 requestInterceptorWrapper 包装,处理请求的派发操作。
- 在回调函数中,首先将
reqOpt(请求配置)赋值给requestOptions,用于后续请求的处理。 - 然后,调用
_dispatchRequest<T>(reqOpt)发起请求,并使用then方法处理请求的结果。如果请求成功,调用handler.resolve(value, true)将结果传递给请求处理器;如果请求失败,使用catchError捕获异常,并调用handler.reject(e as DioError, true)将异常传递给请求处理器。 - 最后,将这个派发请求的回调函数包装成一个回调函数,并添加到请求流程中。
这样,请求流程中已经添加了所有的请求拦截器和派发请求的回调函数,它们会按照先进先出的顺序执行,并在请求流程中逐步处理请求和响应。
Add response interceptors to request flow
// Add response interceptors to request flow
for (final interceptor in interceptors) {
final fun = interceptor is QueuedInterceptor ? interceptor._handleResponse : interceptor.onResponse;
future = future.then(responseInterceptorWrapper(fun));
}
// Add error handlers to request flow
for (final interceptor in interceptors) {
final fun = interceptor is QueuedInterceptor ? interceptor._handleError : interceptor.onError;
future = future.catchError(errorInterceptorWrapper(fun));
}
// Normalize errors, we convert error to the DioError.
return future.then<Response<T>>((data) {
return assureResponse<T>(
data is InterceptorState ? data.data : data,
requestOptions,
);
}).catchError((Object e) {
final isState = e is InterceptorState;
if (isState) {
if (e.type == InterceptorResultType.resolve) {
return assureResponse<T>(e.data, requestOptions);
}
}
throw assureDioError(isState ? e.data : e, requestOptions);
});
这段代码向请求流程中添加了响应拦截器和错误处理器,并对错误进行了规范化处理。
具体解释如下:
- 首先,通过
for循环遍历interceptors列表,其中的每个元素都是一个拦截器。 - 对于每个拦截器,使用条件判断
interceptor is QueuedInterceptor来确定使用不同的处理函数。如果是QueuedInterceptor类型的拦截器,则使用_handleResponse函数作为响应拦截器;否则使用onResponse函数作为响应拦截器。将相应的处理函数赋值给变量fun。 - 然后,通过
future.then(responseInterceptorWrapper(fun))将处理函数包装成一个回调函数,并将其添加到请求流程中。responseInterceptorWrapper函数用于包装拦截器的处理函数,使其能够在异步任务中执行,并处理回调结果。 - 循环结束后,请求流程中已经添加了所有的响应拦截器。
接下来,通过另一个 for 循环遍历 interceptors 列表,向请求流程中添加了错误处理器。
- 对于每个拦截器,使用条件判断
interceptor is QueuedInterceptor来确定使用不同的处理函数。如果是QueuedInterceptor类型的拦截器,则使用_handleError函数作为错误处理器;否则使用onError函数作为错误处理器。将相应的处理函数赋值给变量fun。 - 通过
future.catchError(errorInterceptorWrapper(fun))将错误处理函数包装成一个回调函数,并将其添加到请求流程中。errorInterceptorWrapper函数用于包装错误处理器的处理函数,使其能够在异步任务中执行,并处理回调结果。
接下来,通过链式调用 then 和 catchError 方法,对请求流程中的结果进行处理。
-
通过
future.then<Response<T>>((data) { ... })方法添加一个回调函数,用于处理请求流程中的结果。在这个回调函数中,根据结果的类型进行规范化处理。 -
如果结果是
InterceptorState类型,则将其数据部分提取出来,即data.data,作为响应数据;如果结果不是InterceptorState类型,则直接将结果作为响应数据。 -
调用
assureResponse<T>(...)方法将响应数据和请求配置传递给assureResponse函数,以获取经过规范化处理的响应对象。 -
最后,通过
catchError方法添加一个回调函数,用于处理请求流程中的错误。在这个回调函数中,首先判断错误是否是InterceptorState类型。 -
如果是
InterceptorState类型,进一步判断其类型是否为InterceptorResultType.resolve。如果是,则将其数据部分作为响应数据,调用 `assureResponse(...) -
在错误处理的回调函数中,如果错误对象的类型是
InterceptorState,则进一步判断其类型是否为InterceptorResultType.resolve。如果是这种情况,表示错误已被处理并解决,可以将其数据部分作为响应数据。 -
如果不是
InterceptorState类型或者不是InterceptorResultType.resolve类型,则需要将错误进行规范化处理。调用assureDioError函数将错误对象和请求配置传递进去,以获得经过规范化处理的DioError对象。 -
最后,使用
throw关键字抛出规范化处理后的错误,以终止请求流程并向上层传递错误。整体来说,这段代码构建了一个请求流程,其中的处理器(拦截器)按照先进先出的顺序执行。首先,添加请求拦截器和请求分发回调函数到请求流程中,然后添加响应拦截器和错误处理器。最后,对请求流程中的结果进行规范化处理,确保返回的响应是经过正确处理的对象。如果出现错误,则将错误规范化处理并向上层抛出。
请注意,这段代码是在异步环境中执行的,使用
Future和then方法来构建异步任务链。
listenCancelForAsyncTask
static Future<T> listenCancelForAsyncTask<T>(CancelToken? cancelToken,
Future<T> future,) {
return Future.any([
if (cancelToken != null) cancelToken.whenCancel.then((e) => throw e),
future,
]);
}
listenCancelForAsyncTask 是一个静态方法,其作用是监听取消令牌(CancelToken)和异步任务,并返回其中最先完成的结果。
cancelToken:取消令牌,用于取消异步任务。future:要执行的异步任务。
方法内部使用了 Future.any 方法,它接受一个 Iterable,并返回其中最先完成的 Future 对象。在这个方法中,我们传入了两个 Future 对象:
- 如果
cancelToken不为空,我们通过cancelToken.whenCancel方法创建了一个Future,当取消令牌触发取消事件时,该Future会抛出对应的取消异常。 future是传入的要执行的异步任务。
因此,listenCancelForAsyncTask 方法返回的是最先完成的 Future 对象,无论是成功完成任务还是被取消。如果取消令牌触发了取消事件,将抛出取消异常,否则返回异步任务的结果。
这个方法的作用是在异步任务执行期间监听取消令牌,并及时处理取消事件,以提供对取消操作的支持。
_dispatchRequest
Future<Response<dynamic>> _dispatchRequest<T>(RequestOptions reqOpt) async {
final cancelToken = reqOpt.cancelToken;
ResponseBody responseBody;
try {
final stream = await _transformData(reqOpt);
responseBody = await httpClientAdapter.fetch(
reqOpt,
stream,
cancelToken?.whenCancel,
);
final headers = Headers.fromMap(responseBody.headers);
// Make sure headers and responseBody.headers point to a same Map
responseBody.headers = headers.map;
final ret = Response<dynamic>(
headers: headers,
requestOptions: reqOpt,
redirects: responseBody.redirects ?? [],
isRedirect: responseBody.isRedirect,
statusCode: responseBody.statusCode,
statusMessage: responseBody.statusMessage,
extra: responseBody.extra,
);
final statusOk = reqOpt.validateStatus(responseBody.statusCode);
if (statusOk || reqOpt.receiveDataWhenStatusError == true) {
ret.data = await transformer.transformResponse(reqOpt, responseBody);
} else {
await responseBody.stream.listen(null).cancel();
}
checkCancelled(cancelToken);
if (statusOk) {
return ret;
} else {
throw DioError.badResponse(
statusCode: responseBody.statusCode,
requestOptions: reqOpt,
response: ret,
);
}
} catch (e) {
throw assureDioError(e, reqOpt);
}
}
_dispatchRequest 是一个私有方法,用于实际发送请求并处理响应。它接受一个 RequestOptions 参数 reqOpt,表示请求的选项。
reqOpt:请求的选项,包括请求的URL、方法、头部、超时设置等信息。
方法内部的逻辑如下:
-
首先获取请求的取消令牌
cancelToken。 -
尝试将请求数据进行转换,获取转换后的数据流
stream。 -
使用
httpClientAdapter发送请求并获取响应的responseBody。同时传入取消令牌的whenCancel方法,以便在取消请求时得到通知。 -
创建响应的头部对象
headers,并确保responseBody.headers和headers引用相同的 Map 对象。 -
创建一个空的
Response<dynamic>对象ret,并将响应相关的信息赋值给该对象。 -
检查响应的状态码是否符合预期,如果符合或者请求选项中设置了在状态码错误时接收响应数据,则进行数据转换。
- 如果状态码符合预期或者需要在状态码错误时接收响应数据,将调用转换器的
transformResponse方法,将响应数据进行转换,并将转换后的结果赋值给ret.data。 - 如果状态码不符合预期且不需要在状态码错误时接收响应数据,则取消响应的数据流。
- 如果状态码符合预期或者需要在状态码错误时接收响应数据,将调用转换器的
-
检查请求是否被取消,如果取消则抛出
DioError异常。 -
根据响应的状态码判断响应是否成功。如果成功,则返回
ret对象作为响应结果。 -
如果响应状态码不符合预期,则抛出
DioError.badResponse异常,其中包含响应的状态码、请求选项和响应对象作为错误信息。 -
如果出现异常,使用
assureDioError方法将异常对象转换为DioError对象,并抛出。
因此,_dispatchRequest 方法的作用是实际发送请求并处理响应。它将请求的数据转换为请求适配器可接受的格式,并使用适配器发送请求并获取响应。然后,根据响应的状态码和请求选项进行处理,最后返回相应的 Response 对象或抛出适当的异常。
assureResponse
static Response<T> assureResponse<T>(Object response,
RequestOptions requestOptions,) {
if (response is! Response) {
return Response<T>(
data: response as T,
requestOptions: requestOptions,
);
} else if (response is! Response<T>) {
final T? data = response.data as T?;
final Headers headers;
if (data is ResponseBody) {
headers = Headers.fromMap(data.headers);
} else {
headers = response.headers;
}
return Response<T>(
data: data,
headers: headers,
requestOptions: response.requestOptions,
statusCode: response.statusCode,
isRedirect: response.isRedirect,
redirects: response.redirects,
statusMessage: response.statusMessage,
extra: response.extra,
);
}
return response;
}
assureResponse 是一个静态方法,用于确保返回的响应对象的类型符合预期。它接受两个参数:response(响应对象)和 requestOptions(请求选项)。
response:要进行类型确认的响应对象。requestOptions:请求选项。
方法内部的逻辑如下:
-
首先检查
response是否是Response类型的实例,如果不是,则将其作为数据(data)进行包装,创建一个新的Response<T>对象,并使用传入的requestOptions进行初始化。 -
如果
response是Response类型的实例,但不是Response<T>类型的实例,那么我们需要根据其数据类型进行进一步处理。- 如果
response.data是ResponseBody类型的实例,我们从中提取头部信息(headers)并创建一个新的Headers对象。 - 否则,我们使用原始响应的头部信息。 最后,我们创建一个新的
Response<T>对象,将数据、头部信息以及其他相关属性(状态码、是否重定向、重定向信息等)复制到新的对象中。
- 如果
-
如果
response的类型已经是Response<T>,则直接返回该对象。
因此,assureResponse 方法的作用是确保返回的响应对象的类型符合预期,并进行必要的类型转换和包装。
assureDioError
static DioError assureDioError(Object err,
RequestOptions requestOptions,) {
if (err is DioError) {
// nothing to be done
return err;
}
return DioError(
requestOptions: requestOptions,
error: err,
);
}
assureDioError 是一个静态方法,用于确保错误对象的类型符合 DioError 的预期。它接受两个参数:err(错误对象)和 requestOptions(请求选项)。
err:要进行类型确认的错误对象。requestOptions:请求选项。
方法内部的逻辑如下:
- 首先检查
err是否已经是DioError类型的实例,如果是,则直接返回该错误对象。 - 如果
err不是DioError类型的实例,我们将其作为错误信息(error)进行包装,并使用传入的requestOptions进行初始化,创建一个新的DioError对象。 - 返回新创建的
DioError对象。
因此,assureDioError 方法的作用是确保错误对象的类型符合 DioError 的预期,并进行必要的类型转换和包装。如果错误对象已经是 DioError 类型的实例,则直接返回该对象,否则创建一个新的 DioError 对象。
addProgress
Stream<Uint8List> addProgress(
Stream<List<int>> stream,
int? length,
RequestOptions options,
) {
final streamTransformer = stream is Stream<Uint8List>
? _transform<Uint8List>(stream, length, options)
: _transform<List<int>>(stream, length, options);
return stream.transform<Uint8List>(streamTransformer);
}
这段代码是一个用于添加进度监听的方法。它接收一个输入流 stream,一个可选的数据长度 length,和请求选项 options,并返回一个带有进度监听的输出流 Stream<Uint8List>。
该方法首先根据输入流的类型来选择适当的 _transform 转换器,并将进度监听添加到流中。然后,使用选择的转换器将输入流转换为 Stream<Uint8List> 类型的输出流,并返回这个输出流。
在 _transform 方法中,具体的进度监听逻辑被处理,用于在数据传输过程中更新进度条等功能。由于 _transform 方法的实现没有提供,无法直接解释其具体细节。不过,通过该方法的整体逻辑可以了解到,它主要是为了实现一个进度监听器,并将其添加到输入流中,以便在数据传输期间获取进度信息。
需要注意的是,该方法适用于处理 Stream<Uint8List> 和 Stream<List<int>> 这两种类型的输入流,并在内部根据输入流的类型选择适合的转换器。
_transform
StreamTransformer<S, Uint8List> _transform<S extends List<int>>(
Stream<S> stream,
int? length,
RequestOptions options,
) {
int complete = 0;
return StreamTransformer<S, Uint8List>.fromHandlers(
handleData: (S data, sink) {
final cancelToken = options.cancelToken;
if (cancelToken != null && cancelToken.isCancelled) {
cancelToken.requestOptions = options;
sink
..addError(cancelToken.cancelError!)
..close();
} else {
if (data is Uint8List) {
sink.add(data);
} else {
sink.add(Uint8List.fromList(data));
}
if (length != null) {
complete += data.length;
if (options.onSendProgress != null) {
options.onSendProgress!(complete, length);
}
}
}
},
);
}
这是一个私有方法 _transform,它是一个通用的流转换器用于处理不同类型的输入流 Stream<S> 并返回 Stream<Uint8List>。
这个方法实现了一个 StreamTransformer<S, Uint8List>,它将输入流中的数据类型 S 转换为 Uint8List 类型,并在转换过程中处理进度监听。
让我们来逐行解释这个方法的具体实现:
-
方法签名:
StreamTransformer<S, Uint8List> _transform<S extends List<int>>(Stream<S> stream, int? length, RequestOptions options)这里使用了泛型
S extends List<int>,表示该方法适用于处理所有类型为List<int>或其子类的输入流。 -
创建局部变量
complete:int complete = 0;该变量用于记录已完成的数据长度,用于计算进度。
-
返回
StreamTransformer<S, Uint8List>.fromHandlers(...)这里使用
StreamTransformer.fromHandlers来创建一个自定义的流转换器,从而实现数据类型转换和进度监听的功能。 -
handleData回调函数:当有新数据传入时,该回调函数将被调用,处理数据的转换和进度监听。
-
handleData: (S data, sink) { ... }这个回调函数接收两个参数:
data表示输入流中的数据,sink是输出流的StreamSink,用于向输出流中添加数据。
-
-
进度监听处理:
- 首先,检查
cancelToken是否存在且是否已被取消,如果是则向输出流添加取消错误,并关闭输出流。 - 如果
data是Uint8List类型,则直接将data添加到输出流。 - 否则,将
data转换为Uint8List类型,然后添加到输出流。 - 如果
length不为null,表示数据的总长度已知,更新complete变量,并通过options.onSendProgress回调通知进度。
- 首先,检查
-
返回
StreamTransformer:将上述处理逻辑封装为
StreamTransformer并返回。
总的来说,这个方法是一个通用的流转换器,用于将输入流的数据类型转换为 Uint8List 并支持进度监听。该方法通常用于 Dio 请求中的数据传输过程,以实现上传进度的功能。