Dio
一. 安裝
在 pubspec.yaml 文件下添加,版本可以自行選擇
dependencies:
dio: ^3.0.9
ctrl+s 保存 或者終端執行 flutter pub get安裝依賴
二. Dio APIS
1. BaseOptions 基礎配置
// 導入
import 'package:dio/dio.dart';
// 根據自身需求進行配置 不需要的可以不用配置 有默認值
Dio dio=new Dio(BaseOptions(
method:"post", //請求方式
connectTimeout:1000, // 連接超時時間
receiveTimeout:2000, // 接收超時時間
sendTimeout:3000, // 發送超時時間
// 基礎Url 後面的請求都是在這個基礎上添加
baseUrl:"http://127.0.0.1:4200",
// 在url後面進行拼接傳遞的參數
queryParameters:{"name":"zs","age":20},
// 自定義字段
extra:{"sport":"run"},
// 設置請求頭
headers:{"Content-Type":"application/json"},
// 其實就是請求頭中的一部分被單獨拎出來
// 用於定義網絡文件的類型和網頁的編碼,決定瀏覽器將以什麼形式、什麼編碼讀取這個文件
contentType:"text/plain;charset=UTF-8",
// 返回值的類似 ResponseType是個枚舉 可以查看其屬性 此處設置爲json類型
responseType: ResponseType.json,
// 有效狀態 status爲狀態碼 可以根據狀態碼決定是否有效
// 返回true則爲有效 可以接收服務器傳遞的數據
// 返回false則無效 發送錯誤 不接收服務器數據
validateStatus:(status){
print(status);
return true;
},
// 允許重定向
followRedirects: true,
// 最大重定向次數
maxRedirects : 5,
));
2. 請求類型的別名
// 基本用法爲:
dio.get(url).then((value)=>{
// 這裏的value爲Response類型 待會會詳解
})
dio.get() // get請求
dio.post() // post請求
dio.put() // put請求
dio.delete() // delete請求
dio.head() // head請求
dio.put() // put請求
dio.patch() // patch請求
dio.download() // 下載文件
3. RequestOptions 請求配置
這是具體不同的請求中使用的配置,會覆蓋基礎配置BaseOptions
基本和BaseOptions一致
4. Response 和 DioError
try {
dio.request("/test").then((value) => {
// 這裏的value是Response類型 常用屬性有
// data 響應數據
// Headers 響應頭 Headers類型
// request 請求配置 RequestOptions類型
// isRedirect 是否重定向
// statusCode 狀態碼
// statusMessage 狀態信息
print(value.data);
})
}on DioError catch(e) {
// 響應信息,它可能是空的 如果請求不能到達http服務器,例如,發生DNS錯誤,網絡是不可用的。
if(e.response) {
print(e.response.data)
print(e.response.headers)
print(e.response.request)
} else{
print(e.request)
print(e.message)
}
// 除了 response 還有
// message 錯誤信息
// type 錯誤類型
// CONNECT_TIMEOUT 連接超時
// RECEIVE_TIMEOUT 接收超時
// RESPONSE 狀態碼錯誤
// CANCEL 請求取消
// DEFAULT 默認錯誤
}
5. Interceptors 攔截器
dio.interceptors.add(InterceptorsWrapper(
// 如何使用? 只需要根據參數的類型 看看這個參數中有哪些屬性 就可以知道如何根據需求操作屬性 以下爲簡單的例子
onRequest:(RequestOptions options) async {
// 此處代碼在請求前執行 在這裏可以對請求進行各種修改
// 如 設置請求頭 應用:可以用於攜帶token
options.headers['token']="token";
// url方式攜帶參數 options中的屬性基本都可以操作 可以根據需要來修改
options.queryParameters={"sprot":"run"};
// lock和unlock的使用
// 1.使用lock鎖定攔截器 使攔截器處於類似暫停的狀態
dio.interceptors.requestLock.lock(); // 簡寫 dio.lock()
// 2. 使用unlock解鎖攔截器,攔截器可以繼續往下運行
// 這裏使用定時器 兩秒後解鎖
Timer(new Duration(seconds: 2),(){
print("解鎖攔截器");
dio.interceptors.requestLock.unlock(); // 簡寫 dio.unlock();
});
// 正常返回
return options;
// 如果需要拒絕 則
// return dio.reject("拒絕");
},
onResponse:(Response response) async {
// 在接收響應數據前指定的代碼 可以對response進行各種修改
// 可以操作返回的數據 如進行拼接
response.data="服務器返回的數據:"+response.data;
return response;
},
onError: (DioError e) async {
// 發送錯誤時執行
// 修改錯誤信息
e.error="My Error!!";
return e;
}
));
6. 取消請求
// 創建一個CancelToken的實例對象
CancelToken token = CancelToken();
// 發送請求時 綁定這個對象
dio.get(url1, cancelToken: token);
dio.get(url2, cancelToken: token);
// 執行cancel()函數 即可取消請求 取消類似於報錯
token.cancel("取消時報錯的信息");
7.Proxy 代理
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate=(client){
client.findProxy=(uri){
// 由這個url代理dio中請求中的url 基本上就是替換了url
return "PROXY localhost:666";
};
};
三. 具體例子
1. post
// data傳遞參數
// data和queryParameters的區別:
// data是隱藏的 queryParameters是拼接在url後面的
dio.post("/test", data: {"name":"Rob"},queryParameters: {
"age":22
}).then((value=>{
print(value);
}));
2. 配合Future等待多個請求執行完畢
// 這個用於當後續的操作需要多個網絡請求的結果時可以使用
Future.wait([dio.post("/task1"), dio.get("/task2")]).then((value)=>{
// 這裏的代碼會在上面兩個請求結束後才執行
});
3. 下載文件
// urlPath爲下載的地址 savePath爲文件保存的地址
// 這個可以配合path_provider進行使用
// path_provider是文件系統相關的插件
dio.download(urlPath, savePath).then((value) => {null});
4. 設置Options中的responseType來控制響應的類型
// 響應類型爲流(Stream)
Response<ResponseBody> rs = await Dio().get<ResponseBody>(url,
options: Options(responseType: ResponseType.stream),
);
print(rs.data.stream);
// 響應類型爲字節(bytes)
Response<List<int>> rs = await Dio().get<List<int>>(url,
options: Options(responseType: ResponseType.bytes),
);
print(rs.data);
5. 上傳文件
// 上傳文件其實也是post的類型 只是對傳遞的data使用FormData進行操作 類似於前端的表單 不僅可以傳輸文件 也可以傳輸普通對象/Map
// 方法一:將Map類型轉換成FormData類型
var formData=FormData.fromMap({
"name": "Rob",
"age": 22,
// 文件路徑 文件名
"file": await MultipartFile.fromFile("./index.txt",filename: "simpleFile.txt"),
"files": [
await MultipartFile.fromFile("./index.txt",filename: "MultiFile1.txt"),
await MultipartFile.fromFile("./index.txt",filename: "MultiFile2.txt"),
]
});
// 方法二:
var formData = FormData();
formData.files.addAll([
MapEntry(
"files",
MultipartFile.fromFileSync("./upload.txt",
filename: "upload1.txt"),
),
MapEntry(
"files",
MultipartFile.fromFileSync("./upload.txt",
filename: "upload2.txt"),
),
]);
response = await dio.post("/getFile",
data: formData,
// 傳輸進度事件 已發送 總共
onSendProgress: (int sent, int total) {
print("$sent $total");
}
);
6. 更改請求頭
// 默認情況下,Dio將請求數據(字符串類型除外)序列化爲JSON。
// 可以根據需求進行修改,如修改爲以application / x-www-form-urlencoded格式發送數據
// 方法一:基礎配置時即設置 dio的請求都變成這個類型
dio.options.contentType= Headers.formUrlEncodedContentType;
// 方法二:發送請求時設置 單個請求爲這個類型 別的請求還是默認JSON
dio.post("/index",
options: Options(contentType:Headers.formUrlEncodedContentType)
);