dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等...html
import 'package:dio/dio.dart';
main() async {
var dio = Dio();
Response response = await dio.get("https://google.com");
print(response.data);
}
複製代碼
在pubspec.yaml文件中添加:git
dependencies:
dio: 2.1.13 #當前最新版本爲2.1.13
複製代碼
默認狀況下, Dio 會將請求數據(除過String類型)序列化爲 JSON. 若是想要以 application/x-www-form-urlencoded格式編碼, 你能夠顯式設置contentType :
複製代碼
//Instance level
dio.options.contentType=ContentType.parse("application/x-www-form-urlencoded");
//or works once
dio.post("/info",data:{"id":5}, options: new Options(contentType:ContentType.parse("application/x-www-form-urlencoded")));
複製代碼
請求示例(get、post)github
一、發起get請求json
Response response;
Dio dio = new Dio();
response = await dio.get("/test?id=12&name=wendu");
print(response.data.toString());
// 請求參數也能夠經過對象傳遞,上面的代碼等同於:
response = await dio.get("/test", queryParameters: {"id": 12, "name": "wendu"});
print(response.data.toString());
複製代碼
二、發起POST請求api
response = await dio.post("/test", data: {"id": 12, "name": "wendu"});
複製代碼
注意: 只有 post 方法支持發送 FormData.數組
FormData formData = new FormData.from({
"name": "wendux",
"age": 25,
});
response = await dio.post("/info", data: formData);
複製代碼
FormData formData = new FormData.from({
"name": "wendux",
"age": 25,
"file1": new UploadFileInfo(new File("./upload.txt"), "upload1.txt"),
//支持直接上傳字節數組 (List<int>) ,方便直接上傳內存中的內容
"file2": new UploadFileInfo.fromBytes(
utf8.encode("hello world"), "word.txt"),
// 支持文件數組上傳
"files": [
new UploadFileInfo(new File("./example/upload.txt"), "upload.txt"),
new UploadFileInfo(new File("./example/upload.txt"), "upload.txt")
]
});
response = await dio.post("/info", data: formData);
複製代碼
三、發起併發請求bash
response = await Future.wait([dio.post("/info"), dio.get("/token")]);
複製代碼
四、下載文件服務器
response = await dio.download("https://www.google.com/", "./xx.html");
複製代碼
五、請求接收方式markdown
Response<ResponseBody> rs = await Dio().get<ResponseBody>(url,
options: Options(responseType: ResponseType.stream), //設置接收類型爲stream);
print(rs.data.stream); //響應流
複製代碼
Response<List<int>> rs = await Dio().get<List<int>>(url,
options: Options(responseType: ResponseType.bytes), //設置接收類型爲bytes);
print(rs.data); //二進制數組
複製代碼
6.監聽發送(上傳)數據速度cookie
response = await dio.post(
"http://www.dtworkroom.com/doris/1/2.0.0/test",
data: {"aa": "bb" * 22},
onSendProgress: (int sent, int total) {
print("$sent $total");
},
);
複製代碼
7.以流的形式提交二進制數據
// 二進制數據
List<int> postData = <int>[...];
await dio.post(
url,
data: Stream.fromIterable(postData.map((e) => [e])), //建立一個Stream<List<int>>
options: Options(
headers: {
HttpHeaders.contentLengthHeader: postData.length, // 設置content-length
},
),
);
若是要監聽提交進度,則必須設置content-length,反之則是可選的。
複製代碼
Dio APIs
DIO核心API代碼以下:
Future request(String path, {data,Map queryParameters, Options options,CancelToken cancelToken, ProgressCallback onSendProgress, ProgressCallback onReceiveProgress)
response = await request(
"/test",
data: {"id": 12, "name": "xx"},
options: Options(method: "GET"),
);
複製代碼
建議在項目中使用Dio單例,這樣即可對同一個dio實例發起的全部請求進行一些統一的配置,好比設置公共header、請求基地址、超時時間等
咱們能夠使用默認配置或傳遞一個可選BaseOptions參數來建立一個Dio實例
Dio dio = new Dio(); // 使用默認配置
// 配置dio實例
dio.options.baseUrl = "https://www.xx.com/api";
dio.options.connectTimeout = 5000; //5s
dio.options.receiveTimeout = 3000;
// 或者經過傳遞一個 `BaseOptions`來建立dio實例
BaseOptions options = new BaseOptions(
baseUrl: "https://www.xx.com/api",
connectTimeout: 5000,
receiveTimeout: 3000,
);
Dio dio = new Dio(options);
複製代碼
下面是全部的請求配置選項。 若是請求method沒有指定,則默認爲GET :
{
/// Http method.
String method;
/// 請求基地址,能夠包含子路徑,如: "https://www.google.com/api/".
String baseUrl;
/// Http請求頭.
Map<String, dynamic> headers;
/// 鏈接服務器超時時間,單位是毫秒.
int connectTimeout;
/// 2.x中爲接收數據的最長時限.
int receiveTimeout;
/// 請求路徑,若是 `path` 以 "http(s)"開始, 則 `baseURL` 會被忽略; 不然,
/// 將會和baseUrl拼接出完整的的url.
String path = "";
/// 請求的Content-Type,默認值是[ContentType.JSON].
/// 若是您想以"application/x-www-form-urlencoded"格式編碼請求數據,
/// 能夠設置此選項爲 `ContentType.parse("application/x-www-form-urlencoded")`, 這樣[Dio]
/// 就會自動編碼請求體.
ContentType contentType;
/// [responseType] 表示指望以那種格式(方式)接受響應數據。
/// 目前 [ResponseType] 接受三種類型 `JSON`, `STREAM`, `PLAIN`.
///
/// 默認值是 `JSON`, 當響應頭中content-type爲"application/json"時,dio 會自動將響應內容轉化爲json對象。
/// 若是想以二進制方式接受響應數據,以下載一個二進制文件,那麼能夠使用 `STREAM`.
///
/// 若是想以文本(字符串)格式接收響應數據,請使用 `PLAIN`.
ResponseType responseType;
/// `validateStatus` 決定http響應狀態碼是否被dio視爲請求成功, 返回`validateStatus`
/// 返回`true` , 請求結果就會按成功處理,不然會按失敗處理.
ValidateStatus validateStatus;
/// 用戶自定義字段,能夠在 [Interceptor]、[Transformer] 和 [Response] 中取到.
Map<String, dynamic> extra;
/// 公共query參數
Map<String, dynamic /*String|Iterable<String>*/ > queryParameters;
}
複製代碼
當請求成功時會返回一個Response對象,它包含以下字段
{
/// 響應數據,可能已經被轉換了類型, 詳情請參考Options中[ResponseType].
var data;
/// 響應頭
HttpHeaders headers;
/// 本次請求信息
Options request;
/// Http status code.
int statusCode;
/// 是否重定向
bool isRedirect;
/// 重定向信息
List<RedirectInfo> redirects ;
/// 最終真正的請求地址(由於可能會重定向)
Uri realUri;
/// 響應對象的自定義字段(能夠在攔截器中設置它),調用方能夠在`then`中獲取.
Map<String, dynamic> extra;
//注:假若有一個url返回的是json數據,返回數據在默認狀況下(options.responseType爲json)會被自動轉爲Json對象(Map或List)的:
}
複製代碼
以請求Google爲例:
Response response = await dio.get("https://www.google.com");
print(response.data);
print(response.headers);
print(response.request);
print(response.statusCode);
複製代碼
咱們在網絡請求中每每須要查看日誌信息,此時就須要添加一個日誌攔截器
dio.interceptors.add(LogInterceptor(responseBody: false)); //開啓請求日誌
複製代碼
在添加攔截器時須要注意,因爲攔截器隊列的執行順序是FIFO,若是把log攔截器添加到了最前面,則後面攔截器對options的更改就不會被打印(但依然會生效),因此建議把log攔截添加到隊尾。
複製代碼
有時在進行請求中須要攔截cookie來自動管理請求/響應cookie,那麼就須要添加依賴
dependencies:
cookie_jar: ^1.0.1
複製代碼
你能夠建立一個CookieJar 或 PersistCookieJar 來幫您自動管理cookie, dio 默認使用 CookieJar , 它會將cookie保存在內存中。
若是您想對cookie進行持久化, 請使用 PersistCookieJar , 示例代碼以下:
var dio = new Dio();
dio.interceptors.add(CookieManager(CookieJar()))
複製代碼
廣泛說來,若是須要建立一些自定義的攔截器,只須要經過繼承Intercepto類來實現便可
當請求過程當中發生錯誤時, Dio 會包裝 Error/Exception 爲一個 DioError:
try {
//404
await dio.get("https://wendux.github.io/xsddddd");
} on DioError catch (e) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx and is also not 304.
if (e.response) {
print(e.response.data);
print(e.response.headers);
print(e.response.request);
} else {
// Something happened in setting up or sending the request that triggered an Error
print(e.request);
print(e.message);
}
}
複製代碼
DioError字段
{
/// 響應信息, 若是錯誤發生在在服務器返回數據以前,它爲 `null`
Response response;
/// 錯誤描述.
String message;
/// 錯誤類型,見下文
DioErrorType type;
///原始的error或exception對象,一般type爲DEFAULT時存在。
dynamic error;
/// 錯誤棧信息,可能爲null
StackTrace stackTrace;
}
複製代碼
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
// config the http client
client.findProxy = (uri) {
//proxy all request to localhost:8888
return "PROXY localhost:8888";
};
// you can also create a new HttpClient to dio
// return new HttpClient();
};
複製代碼
能夠經過 cancel token 來取消發起的請求:
CancelToken token = new CancelToken();
dio.get(url, cancelToken: token)
.catchError((DioError err){
if (CancelToken.isCancel(err)) {
print('Request canceled! '+ err.message)
}else{
// handle error.
}
});
// cancel the requests with "cancelled" message.
token.cancel("cancelled");
複製代碼