Dio网络请求框架之Dio、DioForNative源码分析(四)

652 阅读22分钟

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类的属性来配置请求的基本选项,如baseUrlconnectTimeoutreceiveTimeout等。
  • interceptors是一个Interceptors类型的属性,用于管理拦截器。拦截器可以在请求过程中对请求和响应进行拦截和修改,以实现一些通用的逻辑,如认证、日志记录等。Interceptors类提供了添加、移除和清空拦截器的方法。
  • httpClientAdapter是一个HttpClientAdapter类型的延迟初始化属性,用于设置和管理HttpClient适配器。适配器是Dio和实际的HttpClient之间的桥梁,负责发起实际的HTTP请求。可以根据需要使用不同的适配器来适应不同的平台和环境,例如dart:io平台下的IOHttpClientAdapterdart:html平台下的BrowserHttpClientAdapter
  • transformer是一个Transformer类型的延迟初始化属性,用于在发送和接收数据之前对请求和响应进行转换。这个属性主要针对请求方法为'PUT'、'POST'和'PATCH'的情况,可以对请求的数据进行转换处理。Transformer类提供了一系列的转换方法,如jsonDecodeTransformerformDataTransformer等,以便于对数据进行序列化和反序列化。

通过这些属性,可以对请求进行全局的配置和管理,包括请求的基本选项、拦截器的添加和移除、适配器的设置以及数据的转换处理。这样可以方便地实现统一的请求处理逻辑,并且可以根据需要进行灵活的配置和扩展。

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。当forcefalse时,Dio客户端会保持活动状态,直到所有活动连接完成。当forcetrue时,任何活动连接都会被立即关闭以释放所有资源。这些被关闭的连接将接收到错误事件,以指示客户端已关闭。在两种情况下,在调用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库中最底层的请求方法,其他方法(如getpostput等)都是基于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);
  }
}