Flutter的網絡請求
一起從0開始學習Flutter!
網絡請求在一個APP的分量還是很重的,我們需要熟練的掌握Http請求部分,在Flutter中我們有三種方式,一種是使用Dart給我們提供的HttpClient,第二種是使用第三方的Http請求庫,第三種是使用Flutter給我們準備好的Dio。我們主要是看後面兩種,第一種比較繁瑣一般也不會使用,如果想要了解的可以自行搜索。
HTTP庫
這是一個基礎的網絡請求庫,我們在使用之前需要先引入這個類庫,在pubspec.yaml中添加:
dependencies:
http: ^0.12.1
添加完成後在右上角會出現一個pub get的按鈕,點擊後可以幫助我們下載這個類庫,然後在我們需要的地方加載該類:
import 'package:http/http.dart';
這樣我們的準備工作就算是完成了,接下來我們開始試一下如果使用Http庫進行網絡請求了:
void doHttpRequest() async{//裏面包含異步請求的時候需要加上asyn關鍵字
var url = "http://www.baidu.com";
var postResponse = await http.post(url,//使用Post請求,在需要等待的時候加上await關鍵字
headers: {"": "", "": ""},//添加請求頭
body: {"": "", "": "",});//添加請求的參數
var response = await http.get(url);//使用get方法,直接請求該地址
if(response.statusCode == 200){//如果返回的狀態碼是200則有正確的返回結果
print("response body = ${response.body}");
}else{//其他的異常狀態碼
print("請求異常${response.statusCode}");
}
}
這是比較簡單進行一次網絡請求,我們也可以根據自己的需要進行一定的封裝,這裏不多介紹,我們主要是使用Flutter給我們準備好的Dio來進行網絡請求。
DIO
套用一下dio中的介紹:
dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等
可以做的事情還是挺多的,我們一點點的進行學習吧。
首先我們需要將它引入到我們項目中:
dependencies:
dio: ^3.0.9 //目前的最新版本是3.0.9
發送一個get請求,我們可以使用兩種形式:
var host = "https://wanandroid.com/wxarticle";
var getResponse = await Dio().get("$host/list/408/1/json?id=404&page=1");//傳統的我們使用的直接請求的方式
var getResponse1 = await Dio().get("$host/list/408/1/json",
queryParameters: {"id":"404","page":"1"});//給我們擴展出來了新的寫法,這樣可以更好的查看參數
我們看下返回信息Response裏都給我們帶來了什麼:
Response({
this.data,//返回回來的數據
this.headers,//響應頭信息
this.request,//請求時帶的信息也返回回來了
this.isRedirect,//是否是重定向,這個字段的是否可用取決於適配器是否支持(不是很理解這個字段)
this.statusCode,//返回的響應碼,成功請求返回200
this.statusMessage,//返回的響應碼的狀態描述,如果是失敗的時候有個簡短的狀態信息
this.redirects,//會將每次重定向的地址以及請求狀態放到這裏,我們可以跟蹤每次的重定向請求
this.extra,//自定義字段,我們可以在發送請求的時候將想要在返回處理的時候需要處理的信息進行存放,在請求響應完成時可以拿到附加信息
})
上面就是在完成一次請求後我們可以獲取到的響應內容,我們看下通過post方式會是怎樣的請求形式:
var postResponse = await Dio().post(host,data: {"name":"403"});
很簡單,只是上面的get關鍵字換成了post,然後傳入我們想要的參數就可以了。我們不僅可以通過get和post這兩個函數進行請求,我們也可以使用Dio給我們準備的request方法,我們可以根據自己想要的靈活配置:
Future<Response<T>> request<T>(
String path, {//請求的地址
data,//post需要傳入的參數
Map<String, dynamic> queryParameters,//get方法的時候可以添加的參數
CancelToken cancelToken,//可以添加網絡取消,網絡取消的監聽都在這裏了
Options options,//網絡的配置,參照下面的詳解
ProgressCallback onSendProgress,//發送網絡請求的進度監聽回調
ProgressCallback onReceiveProgress,//接收數據返回的進度監聽回調
});
options
網絡請求的配置,我們可以通過它來設置請求頭和連接超時的設置,看下我們怎麼配置一個網絡請求的:
RequestOptions({
String method,//網絡請求的方法
int sendTimeout,//發送的超時時間
int receiveTimeout,//接受超時時間
this.connectTimeout,//鏈接超時的時間
this.data,//post請求數據時傳遞的參數
this.path,//如果是我們用了http或者https開頭則會忽略baseUrl的設置,如果沒有,則拼接到baseUrl後面
this.queryParameters,//使用get方法時候的參數拼接
this.baseUrl,//請求的根網址
this.onReceiveProgress,//在收到消息時的進度
this.onSendProgress,//在發送消息時的進度
this.cancelToken,//可以添加網絡取消,網絡取消的監聽都在這裏了
Map<String, dynamic> extra,//額外的參數配置,可以在返回的數據中獲取到
Map<String, dynamic> headers,//請求頭
ResponseType responseType,//響應類型,可以是json,可以是數據流,可以是json
String contentType,//設置內容的類型
ValidateStatus validateStatus,//給設定一個響應碼,如果是返回了True則表示請求成功
bool receiveDataWhenStatusError = true,//是否在Http的響應碼是失敗的時候接收響應數據
bool followRedirects = true,//是否可以重定向
int maxRedirects,//最多可以重定向的次數
RequestEncoder requestEncoder,//我們可以設置在發送請求時對請求進行編碼,默認是utf-8的編碼,可以根據需求進行修改
ResponseDecoder responseDecoder,//當我們接收返回消息時對內容進行解碼,默認是utf-8,可以根據需求進行修改
})
這是在我們使用dio的request方法的時候傳入的option,在get和post方法的時候我們也看到有一個option,這兩個傳入的option還有一些小區別,我們看下在get和post的時候我們傳入的option:
BaseOptions({
String method,//網絡請求的方法
this.connectTimeout,//鏈接超時的時間
int receiveTimeout,//接受超時時間
int sendTimeout,//發送的超時時間
this.baseUrl,//設置一個根地址
this.queryParameters,//在get方法的時候作爲拼接的參數
Map<String, dynamic> extra,//在請求時的攜帶的額外信息
Map<String, dynamic> headers,//請求頭
ResponseType responseType = ResponseType.json,//響應類型,可以是json,可以是數據流
String contentType,//設置內容的類型
ValidateStatus validateStatus,//給設定一個響應碼,如果是返回了True則表示請求成功
bool receiveDataWhenStatusError = true,//是否在Http的響應碼是失敗的時候接收響應數據
bool followRedirects = true,//是否可以重定向
int maxRedirects = 5,//最多可以重定向的次數
RequestEncoder requestEncoder,//我們可以設置在發送請求時對請求進行編碼,默認是utf-8的編碼,可以根據需求進行修改
ResponseDecoder responseDecoder,//當我們接收返回消息時對內容進行解碼,默認是utf-8,可以根據需求進行修改
})
再看下我們如何來做消息的攔截:
dio.interceptors.add(InterceptorsWrapper(
onRequest:(options){//發送請求時的過濾
if(options.extra["data"] == 1)
options.cancelToken.cancel("");//我們可以根據自己的設定過濾來取消請求
},
onResponse:(response){//在接收到數據響應的時候過濾
},
onError:(error){//在接收到錯誤信息的時候的攔截
}
));
在網絡請求過程中我們有時候還遇到過鏈式請求,需要在一次請求完成後進行下一次請求,我們看下如何實現這樣的一個鏈式請求:
await Future.wait([dio.get(""),dio.post("")],);//我們可以直接寫入多個網絡請求,Future可以在一次請求完成後進行下一次的請求
使用Dio我們可以進行文件的上傳下載,使用也是比較簡單:
//對文件進行下載
dio.download("下載地址", "保存在本地的地址",onReceiveProgress: (count,total){
print("已經完成的下載量${count},需要下載的文件大小${total}");
});
//對文件進行上傳
var file = MultipartFile.fromFile("本地文件路徑",filename: "文件名");//先獲取到File的對象
var formData = FormData.fromMap({
"file1":file,//將File對象傳入到待上傳的map中
});
dio.post(host,data:formData);//開始文件的上傳
Dio的基本使用就差不多了,我們可以對它進行封裝,這樣每次在進行請求不用每個請求單獨去做設置了,網上有很多大神給我們提供的封裝案例,在這裏不多描述,以後可以做一個通用的封裝給大家。