Dio(抽象类)
abstract class Dio {
factory Dio([BaseOptions? options]) => createDio(options);
}
工厂构造函数Dio接受一个可选的BaseOptions参数,并通过调用createDio方法来创建一个Dio实例。工厂构造函数的作用是提供一个方便的方式来创建Dio对象,并且可以根据需要传递初始配置选项。
抽象方法createDio需要在实现Dio类的子类中进行定义。它用于创建具体的Dio对象,并可以根据需要初始化配置选项。由于该方法是抽象的,因此在Dio类本身中并没有给出具体的实现。子类需要实现这个方法来创建实际可用的Dio对象。
通过工厂构造函数和抽象方法的组合,Dio类提供了一个可定制的创建方式,使得在创建Dio对象时可以灵活地配置选项和实现适用的逻辑。
辅助属性
/// Default Request config. More see [BaseOptions] .
late BaseOptions options;
Interceptors get interceptors;
late HttpClientAdapter httpClientAdapter;
/// [transformer] allows changes to the request/response data before it is sent/received to/from the server
/// This is only applicable for request methods 'PUT', 'POST', and 'PATCH'.
late Transformer transformer;
在Dio类中,有一些属性用于配置和管理请求。
options是一个BaseOptions类型的延迟初始化属性,用于设置默认的请求配置。可以通过BaseOptions类的属性来配置请求的基本选项,如baseUrl、connectTimeout、receiveTimeout等。interceptors是一个Interceptors类型的属性,用于管理拦截器。拦截器可以在请求过程中对请求和响应进行拦截和修改,以实现一些通用的逻辑,如认证、日志记录等。Interceptors类提供了添加、移除和清空拦截器的方法。httpClientAdapter是一个HttpClientAdapter类型的延迟初始化属性,用于设置和管理HttpClient适配器。适配器是Dio和实际的HttpClient之间的桥梁,负责发起实际的HTTP请求。可以根据需要使用不同的适配器来适应不同的平台和环境,例如dart:io平台下的IOHttpClientAdapter或dart:html平台下的BrowserHttpClientAdapter。transformer是一个Transformer类型的延迟初始化属性,用于在发送和接收数据之前对请求和响应进行转换。这个属性主要针对请求方法为'PUT'、'POST'和'PATCH'的情况,可以对请求的数据进行转换处理。Transformer类提供了一系列的转换方法,如jsonDecodeTransformer、formDataTransformer等,以便于对数据进行序列化和反序列化。
通过这些属性,可以对请求进行全局的配置和管理,包括请求的基本选项、拦截器的添加和移除、适配器的设置以及数据的转换处理。这样可以方便地实现统一的请求处理逻辑,并且可以根据需要进行灵活的配置和扩展。
close
/// Shuts down the dio client.
///
/// If [force] is `false` (the default) the [Dio] will be kept alive
/// until all active connections are done. If [force] is `true` any active
/// connections will be closed to immediately release all resources. These
/// closed connections will receive an error event to indicate that the client
/// was shut down. In both cases trying to establish a new connection after
/// calling [close] will throw an exception.
void close({bool force = false});
close方法用于关闭Dio客户端。
force参数是一个布尔值,默认为false。当force为false时,Dio客户端会保持活动状态,直到所有活动连接完成。当force为true时,任何活动连接都会被立即关闭以释放所有资源。这些被关闭的连接将接收到错误事件,以指示客户端已关闭。在两种情况下,在调用close之后尝试建立新的连接将抛出异常。
通过调用close方法,可以显式地关闭Dio客户端,并释放相关资源。这在应用程序结束或不再需要进行网络请求时非常有用。
get
/// Handy method to make http GET request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> get<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
});
get方法是一个方便的方法,用于发起 HTTP GET 请求。它是dio.fetch(RequestOptions)方法的别名。
path参数是请求的路径,是一个字符串类型。data参数是可选的请求数据,可以是任意类型的对象。默认为null。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>类型,用于添加到请求的 URL 中。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onReceiveProgress参数是可选的进度回调函数,是一个ProgressCallback类型,用于监听接收响应的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用get方法可以方便地发送 HTTP GET 请求,并获取响应数据。
getUri
/// Handy method to make http GET request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> getUri<T>(
Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
});
getUri方法是一个方便的方法,用于发起 HTTP GET 请求,它是dio.fetch(RequestOptions)方法的别名。
uri参数是请求的完整 URI,是一个Uri对象。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onReceiveProgress参数是可选的进度回调函数,是一个ProgressCallback类型,用于监听接收响应的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用getUri方法可以方便地发送 HTTP GET 请求,并获取响应数据。传入完整的 URI 可以更灵活地控制请求的目标地址。
post
/// Handy method to make http POST request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> post<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
post方法是一个方便的方法,用于发起 HTTP POST 请求,它是dio.fetch(RequestOptions)方法的别名。
path参数是请求的路径,是一个字符串。data参数是可选的请求数据,可以是任意类型的对象。默认为null。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>对象,用于在请求路径中添加查询参数。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onSendProgress参数是可选的发送进度回调函数,是一个ProgressCallback类型,用于监听发送请求的进度。onReceiveProgress参数是可选的接收进度回调函数,是一个ProgressCallback类型,用于监听接收响应的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用post方法可以方便地发送 HTTP POST 请求,并获取响应数据。可以通过传入路径、数据、查询参数等来定制请求的目标地址和内容。
postUri
/// Handy method to make http POST request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> postUri<T>(
Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
postUri方法是一个方便的方法,用于发起 HTTP POST 请求,它是dio.fetch(RequestOptions)方法的别名。
uri参数是请求的目标 URI,是一个Uri对象,包含了请求的协议、主机、路径等信息。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onSendProgress参数是可选的发送进度回调函数,是一个ProgressCallback类型,用于监听发送请求的进度。onReceiveProgress参数是可选的接收进度回调函数,是一个ProgressCallback类型,用于监听接收响应的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用postUri方法可以方便地发送 HTTP POST 请求,并获取响应数据。可以通过传入目标 URI、数据等来定制请求的目标地址和内容。
put
/// Handy method to make http PUT request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> put<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
put方法是一个方便的方法,用于发起 HTTP PUT 请求,它是dio.fetch(RequestOptions)方法的别名。
path参数是请求的路径,表示请求的目标资源路径。data参数是可选的请求数据,可以是任意类型的对象。默认为null。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>类型,用于设置请求的查询参数。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onSendProgress参数是可选的发送进度回调函数,是一个ProgressCallback类型,用于监听发送请求的进度。onReceiveProgress参数是可选的接收进度回调函数,是一个ProgressCallback类型,用于监听接收响应的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用put方法可以方便地发送 HTTP PUT 请求,并获取响应数据。可以通过传入路径、数据、查询参数等来定制请求的目标地址和内容。
putUri
/// Handy method to make http PUT request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> putUri<T>(
Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
putUri方法是一个方便的方法,用于发起 HTTP PUT 请求,它是dio.fetch(RequestOptions)方法的别名。
uri参数是请求的目标URI,表示请求的目标资源的完整地址。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onSendProgress参数是可选的发送进度回调函数,是一个ProgressCallback类型,用于监听发送请求的进度。onReceiveProgress参数是可选的接收进度回调函数,是一个ProgressCallback类型,用于监听接收响应的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用putUri方法可以方便地发送 HTTP PUT 请求,并获取响应数据。可以通过传入完整的目标地址、数据等来定制请求的目标和内容。
head
/// Handy method to make http HEAD request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> head<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
});
head方法是一个方便的方法,用于发起 HTTP HEAD 请求,它是dio.fetch(RequestOptions)方法的别名。
path参数是请求的路径,表示请求的目标资源的路径部分。data参数是可选的请求数据,可以是任意类型的对象。默认为null。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>类型,用于指定请求的查询参数。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用head方法可以方便地发送 HTTP HEAD 请求,该请求方法通常用于获取资源的元数据而不返回实际的响应体。可以通过传入路径、数据、查询参数等来定制请求的目标和内容。
headUri
/// Handy method to make http HEAD request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> headUri<T>(
Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
});
headUri方法是一个方便的方法,用于发起 HTTP HEAD 请求,它是dio.fetch(RequestOptions)方法的别名。
uri参数是请求的完整 URI,表示请求的目标资源的完整路径,包括协议、主机、路径和查询参数等信息。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用headUri方法可以方便地发送 HTTP HEAD 请求,该请求方法通常用于获取资源的元数据而不返回实际的响应体。可以通过传入完整的 URI、数据、请求配置等来定制请求的目标和内容。
delete
/// Handy method to make http DELETE request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> delete<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
});
delete方法是一个方便的方法,用于发起 HTTP DELETE 请求,它是dio.fetch(RequestOptions)方法的别名。
path参数是请求的路径,表示请求的目标资源的路径部分,不包括协议、主机和查询参数等信息。data参数是可选的请求数据,可以是任意类型的对象。默认为null。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>类型的对象,用于设置请求的查询参数。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用delete方法可以方便地发送 HTTP DELETE 请求,该请求方法用于删除指定的资源。可以通过传入路径、数据、查询参数、请求配置等来定制请求的目标和内容。
deleteUri
/// Handy method to make http DELETE request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> deleteUri<T>(
Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
});
deleteUri方法是一个方便的方法,用于发起 HTTP DELETE 请求,它是dio.fetch(RequestOptions)方法的别名。
uri参数是请求的完整 URI,包括协议、主机、路径和查询参数等信息。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用deleteUri方法可以方便地发送 HTTP DELETE 请求,该请求方法用于删除指定的资源。可以通过传入完整的 URI、数据、请求配置等来定制请求的目标和内容。
patch
/// Handy method to make http PATCH request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> patch<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
patch方法是一个方便的方法,用于发起 HTTP PATCH 请求,它是dio.fetch(RequestOptions)方法的别名。
path参数是请求的路径,不包括协议和主机部分。data参数是可选的请求数据,可以是任意类型的对象。默认为null。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>对象,用于设置请求的查询参数。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onSendProgress参数是可选的请求进度回调函数,用于监听请求发送的进度。onReceiveProgress参数是可选的响应进度回调函数,用于监听响应接收的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用patch方法可以方便地发送 HTTP PATCH 请求,该请求方法用于部分更新资源。可以通过传入路径、数据、查询参数、请求配置等来定制请求的目标和内容
patchUri
/// Handy method to make http PATCH request, which is a alias of [dio.fetch(RequestOptions)].
Future<Response<T>> patchUri<T>(
Uri uri, {
Object? data,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
patchUri方法是一个方便的方法,用于发起 HTTP PATCH 请求,它是dio.fetch(RequestOptions)方法的别名。
uri参数是请求的完整URI,包括协议、主机和路径部分。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消请求。onSendProgress参数是可选的请求进度回调函数,用于监听请求发送的进度。onReceiveProgress参数是可选的响应进度回调函数,用于监听响应接收的进度。
该方法返回一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中T表示响应数据的类型。在请求失败时,会抛出一个异常。
使用patchUri方法可以方便地发送 HTTP PATCH 请求,该请求方法用于部分更新资源。可以通过传入完整的URI、数据、请求配置等来定制请求的目标和内容。
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,
});
download方法用于下载文件。
urlPath参数是下载文件的URL路径。savePath参数是保存下载文件的路径,可以是文件路径字符串或File对象。onReceiveProgress参数是可选的进度回调函数,用于监听下载进度。queryParameters参数是可选的查询参数,是一个Map<String, dynamic>对象,用于向URL添加查询参数。cancelToken参数是可选的取消令牌,是一个CancelToken对象,用于取消下载操作。deleteOnError参数是一个布尔值,指示在下载过程中发生错误时是否删除已下载的部分文件。默认为true,即在发生错误时删除已下载的文件。lengthHeader参数是下载文件的长度头部字段,默认为Content-Length。data参数是可选的请求数据,可以是任意类型的对象。默认为null。options参数是可选的请求配置,是一个Options对象,可以设置请求的各种选项,例如请求头、超时时间等。
该方法返回一个Future<Response>对象,表示异步操作的结果。在下载成功时,会返回一个Response对象,其中包含下载文件的相关信息。在下载失败时,会抛出一个异常。
通过调用download方法可以实现文件的下载功能,指定下载文件的URL路径和保存路径,并可以设置进度回调函数、查询参数、取消令牌等。在下载过程中可以实时获取下载进度,并根据需要进行错误处理和文件操作。
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方法是download方法的一个简化版本,用于下载指定URI的文件。
该方法接受以下参数:
uri:要下载文件的URI。savePath:保存下载文件的路径,可以是文件路径字符串或File对象。onReceiveProgress:可选的进度回调函数,用于监听下载进度。cancelToken:可选的取消令牌,用于取消下载操作。deleteOnError:一个布尔值,指示在下载过程中发生错误时是否删除已下载的部分文件。默认为true。lengthHeader:下载文件的长度头部字段,默认为Headers.contentLengthHeader。data:可选的请求数据,可以是任意类型的对象。options:可选的请求配置,用于设置请求的各种选项。
该方法内部调用了download方法,并将参数传递给download方法进行下载操作。
返回的是一个Future<Response>对象,表示异步操作的结果。在下载成功时,会返回一个Response对象,其中包含下载文件的相关信息。在下载失败时,会抛出一个异常。
request
/// Make http request with options.
///
/// [path] The url path.
/// [data] The request data
/// [options] The request options.
Future<Response<T>> request<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
CancelToken? cancelToken,
Options? options,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
request方法用于发送HTTP请求,并返回一个Future<Response<T>>对象,表示异步操作的结果。
该方法接受以下参数:
path:请求的URL路径。data:请求数据。queryParameters:请求的查询参数。cancelToken:可选的取消令牌,用于取消请求操作。options:可选的请求选项,包括请求头、超时时间等配置。onSendProgress:可选的请求发送进度回调函数,用于监听请求发送的进度。onReceiveProgress:可选的响应接收进度回调函数,用于监听响应接收的进度。
该方法内部调用了fetch方法,并根据传入的参数构建了相应的RequestOptions对象。然后将RequestOptions对象传递给fetch方法进行实际的请求操作。
返回的是一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中包含响应的相关信息和数据。在请求失败时,会抛出一个异常。
requestUri
Future<Response<T>> requestUri<T>(
Uri uri, {
Object? data,
CancelToken? cancelToken,
Options? options,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
requestUri方法用于发送HTTP请求,并返回一个Future<Response<T>>对象,表示异步操作的结果。
该方法接受以下参数:
uri:请求的完整URI。data:请求数据。cancelToken:可选的取消令牌,用于取消请求操作。options:可选的请求选项,包括请求头、超时时间等配置。onSendProgress:可选的请求发送进度回调函数,用于监听请求发送的进度。onReceiveProgress:可选的响应接收进度回调函数,用于监听响应接收的进度。
该方法内部调用了fetch方法,并根据传入的参数构建了相应的RequestOptions对象。然后将RequestOptions对象传递给fetch方法进行实际的请求操作。
返回的是一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中包含响应的相关信息和数据。在请求失败时,会抛出一个异常。
fetch
Future<Response<T>> fetch<T>(RequestOptions requestOptions);
fetch方法用于发送HTTP请求,并返回一个Future<Response<T>>对象,表示异步操作的结果。
该方法接受一个RequestOptions对象作为参数,其中包含了请求的相关配置,如请求方法、URI、请求头、请求数据等。
返回的是一个Future<Response<T>>对象,表示异步操作的结果。在请求成功时,会返回一个Response<T>对象,其中包含响应的相关信息和数据。在请求失败时,会抛出一个异常。
该方法是Dio库中最底层的请求方法,其他方法(如get、post、put等)都是基于fetch方法实现的简化封装。通过直接调用fetch方法,可以更灵活地控制请求的细节和处理请求的响应。
Dio createDio
/// Create the [Dio] instance for native platforms.
Dio createDio([BaseOptions? baseOptions]) => DioForNative(baseOptions);
DioForNative(实现类)
/// Implements features for [Dio] on native platforms.
class DioForNative with DioMixin implements Dio {
/// Create Dio instance with default [BaseOptions].
/// It is recommended that an application use only the same DIO singleton.
DioForNative([BaseOptions? baseOptions]) {
options = baseOptions ?? BaseOptions();
httpClientAdapter = IOHttpClientAdapter();
}
/// {@macro dio.Dio.download}
@override
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,
}) async {
options ??= DioMixin.checkOptions('GET', options);
// Manually set the `responseType` to [ResponseType.stream]
// to retrieve the response stream.
// Do not modify previous options.
options = options.copyWith(responseType: ResponseType.stream);
final Response<ResponseBody> response;
try {
response = await request<ResponseBody>(
urlPath,
data: data,
options: options,
queryParameters: queryParameters,
cancelToken: cancelToken,
);
} on DioException catch (e) {
if (e.type == DioExceptionType.badResponse) {
final response = e.response!;
if (response.requestOptions.receiveDataWhenStatusError == true) {
final ResponseType implyResponseType;
final contentType = response.headers.value(Headers.contentTypeHeader);
if (contentType != null && contentType.startsWith('text/')) {
implyResponseType = ResponseType.plain;
} else {
implyResponseType = ResponseType.json;
}
final res = await transformer.transformResponse(
response.requestOptions.copyWith(responseType: implyResponseType),
response.data as ResponseBody,
);
response.data = res;
} else {
response.data = null;
}
}
rethrow;
}
final File file;
if (savePath is FutureOr<String> Function(Headers)) {
// Add real Uri and redirect information to headers.
response.headers
..add('redirects', response.redirects.length.toString())
..add('uri', response.realUri.toString());
file = File(await savePath(response.headers));
} else if (savePath is String) {
file = File(savePath);
} else {
throw ArgumentError.value(
savePath.runtimeType,
'savePath',
'The type must be `String` or `FutureOr<String> Function(Headers)`.',
);
}
// If the file already exists, the method fails.
file.createSync(recursive: true);
// Shouldn't call file.writeAsBytesSync(list, flush: flush),
// because it can write all bytes by once. Consider that the file is
// a very big size (up to 1 Gigabytes), it will be expensive in memory.
RandomAccessFile raf = file.openSync(mode: FileMode.write);
// Create a Completer to notify the success/error state.
final completer = Completer<Response>();
int received = 0;
// Stream<Uint8List>
final stream = response.data!.stream;
bool compressed = false;
int total = 0;
final contentEncoding = response.headers.value(
Headers.contentEncodingHeader,
);
if (contentEncoding != null) {
compressed = ['gzip', 'deflate', 'compress'].contains(contentEncoding);
}
if (lengthHeader == Headers.contentLengthHeader && compressed) {
total = -1;
} else {
total = int.parse(response.headers.value(lengthHeader) ?? '-1');
}
Future<void>? asyncWrite;
bool closed = false;
Future<void> closeAndDelete() async {
if (!closed) {
closed = true;
await asyncWrite;
await raf.close().catchError((_) => raf);
if (deleteOnError && file.existsSync()) {
await file.delete().catchError((_) => file);
}
}
}
late StreamSubscription subscription;
subscription = stream.listen(
(data) {
subscription.pause();
// Write file asynchronously
asyncWrite = raf.writeFrom(data).then((result) {
// Notify progress
received += data.length;
onReceiveProgress?.call(received, total);
raf = result;
if (cancelToken == null || !cancelToken.isCancelled) {
subscription.resume();
}
}).catchError((Object e) async {
try {
await subscription.cancel().catchError((_) {});
closed = true;
await raf.close().catchError((_) => raf);
if (deleteOnError && file.existsSync()) {
await file.delete().catchError((_) => file);
}
} finally {
completer.completeError(
DioMixin.assureDioException(e, response.requestOptions),
);
}
});
},
onDone: () async {
try {
await asyncWrite;
closed = true;
await raf.close().catchError((_) => raf);
completer.complete(response);
} catch (e) {
completer.completeError(
DioMixin.assureDioException(e, response.requestOptions),
);
}
},
onError: (e) async {
try {
await closeAndDelete();
} finally {
completer.completeError(
DioMixin.assureDioException(e, response.requestOptions),
);
}
},
cancelOnError: true,
);
cancelToken?.whenCancel.then((_) async {
await subscription.cancel();
await closeAndDelete();
});
return DioMixin.listenCancelForAsyncTask(cancelToken, completer.future);
}
}