Flutter Http網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)詳解
Http網(wǎng)絡(luò)請(qǐng)求是一門開發(fā)語言里比較常用和重要的功能,主要用于資源訪問、接口數(shù)據(jù)請(qǐng)求和提交、上傳下載文件等等操作,Http請(qǐng)求方式主要有:GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS。本文主要GET和POST這兩種常用請(qǐng)求在Flutter中的用法,其中對(duì)POST將進(jìn)行著重講解。Flutter的Http網(wǎng)絡(luò)請(qǐng)求的實(shí)現(xiàn)主要分為三種:io.dart里的HttpClient實(shí)現(xiàn)、Dart原生http請(qǐng)求庫實(shí)現(xiàn)、第三方庫實(shí)現(xiàn)。后面將會(huì)給大家詳細(xì)講解這幾種區(qū)別和特點(diǎn)及前兩種的使用方法。接下來,我們就開始Flutter的Http網(wǎng)絡(luò)請(qǐng)求詳解吧。
本文將主要介紹:
- 簡(jiǎn)單介紹這幾種Http請(qǐng)求方式
- Flutter三種Http網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)的區(qū)別和特點(diǎn)
- HttpClient實(shí)現(xiàn)Http網(wǎng)絡(luò)請(qǐng)求
- Dart原生http請(qǐng)求庫實(shí)現(xiàn)Http網(wǎng)絡(luò)請(qǐng)求
- 第三方庫的推薦
1. Http的請(qǐng)求方式簡(jiǎn)介
Http網(wǎng)絡(luò)請(qǐng)求方式就是描述了客戶端想對(duì)指定的資源或服務(wù)器所要執(zhí)行的操作。開頭簡(jiǎn)介里介紹過,Http網(wǎng)絡(luò)請(qǐng)求是一門開發(fā)語言里比較常用和重要的功能,主要用于資源訪問、接口數(shù)據(jù)請(qǐng)求和提交、上傳下載文件等等操作。其中主要的請(qǐng)求方式有:GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS這八種。接下來先簡(jiǎn)單介紹它們的特點(diǎn)和作用。
1.1 GET請(qǐng)求方式
從GET這個(gè)單詞上也可以看出,它主要是執(zhí)行獲取資源操作的,例如通過URL從服務(wù)器獲取返回的資源,其中GET可以把請(qǐng)求的一些參數(shù)信息拼接在URL上,傳遞給服務(wù)器,由服務(wù)器端進(jìn)行參數(shù)信息解析,然后返回相應(yīng)的資源給請(qǐng)求者。注意:GET請(qǐng)求拼接的URL數(shù)據(jù)大小和長(zhǎng)度是有最大限制的,傳輸?shù)臄?shù)據(jù)量一般限制在2KB。
1.2 POST請(qǐng)求方式
POST主要是執(zhí)行提交信息、傳輸信息的操作,POST請(qǐng)求的可以攜帶很多的數(shù)據(jù),而且格式不限。如JSON、XML、文本等等都支持。并且POST傳遞的一些數(shù)據(jù)和參數(shù)不是直接拼接在URL后的,而是放在Http請(qǐng)求Body里,相對(duì)GET來說比較安全。并且傳遞的數(shù)據(jù)大小和格式是無限制的。POST請(qǐng)求方式是比較重要和常用的一種,POST請(qǐng)求包含兩部分:請(qǐng)求頭(header)和請(qǐng)求體(body)。POST請(qǐng)求常見的請(qǐng)求體(body)有三種傳輸內(nèi)容類型Content-type:application/x-www-form-urlencoded、application/json、multipart/form-data,當(dāng)然還有其他的幾種,不過不常用,常用的就是這三種。
1.3 HEAD請(qǐng)求方式
HEAD主要是執(zhí)行給請(qǐng)求的客戶端返回頭信息,而不返回Body主體內(nèi)容。和GET方式類似,只不過GET方式有Body實(shí)體返回,而HEAD只返回頭信息,無Body實(shí)體內(nèi)容返回。主要是用于確認(rèn)URL的有效性、資源更新的日期時(shí)間、查看服務(wù)器狀態(tài)等等,對(duì)于有這方面需求的請(qǐng)求來說,比較不占用資源。
1.4 PUT請(qǐng)求方式
PUT主要是執(zhí)行傳輸文件操作,類似于FTP的文件上傳一樣,請(qǐng)求里包含文件內(nèi)容,并將此文件保存到URI指定的服務(wù)器位置。和POST方式的主要區(qū)別是:PUT請(qǐng)求方式如果前后兩個(gè)請(qǐng)求相同,則后一個(gè)請(qǐng)求會(huì)把前一個(gè)請(qǐng)求覆蓋掉,實(shí)現(xiàn)了PUT方式的修改資源;而POST請(qǐng)求方式如果前后兩個(gè)請(qǐng)求相同,則后一個(gè)請(qǐng)求不會(huì)把前一個(gè)請(qǐng)求覆蓋掉,實(shí)現(xiàn)了POST的增加資源。
1.5 DELETE請(qǐng)求方式
DELETE主要是執(zhí)行告訴服務(wù)器想要?jiǎng)h除的資源,執(zhí)行刪除指定資源操作。
1.6 OPTIONS請(qǐng)求方式
OPTIONS主要是執(zhí)行查詢針對(duì)所要請(qǐng)求的URI資源服務(wù)器所支持的請(qǐng)求方式,也就是獲取這個(gè)URI所支持客戶端提交給服務(wù)器端的請(qǐng)求方式有哪些。
1.7 TRACE請(qǐng)求方式
TRACE主要是執(zhí)行追蹤傳輸路徑的操作,例如,我們發(fā)起了一個(gè)Http請(qǐng)求,在這個(gè)過程中這個(gè)請(qǐng)求可能會(huì)經(jīng)過很多個(gè)路徑和過程,TRACE就是告訴服務(wù)器在收到請(qǐng)求后,返回一條響應(yīng)信息,將它收到的原始Http請(qǐng)求信息返回給客戶端,這樣就可以確認(rèn)在Http傳輸過程中請(qǐng)求是否被修改過。
1.8 CONNECT請(qǐng)求方式
CONNECT主要就是執(zhí)行連接代理操作??蛻舳送ㄟ^CONNECT方式與服務(wù)器建立通信隧道,進(jìn)行TCP通信。主要通過SSL和TLS安全傳輸數(shù)據(jù)。CONNECT的作用就是告訴服務(wù)器讓它代替客戶端去請(qǐng)求訪問某個(gè)資源,然后再將數(shù)據(jù)返回給客戶端,相當(dāng)于一個(gè)媒介中轉(zhuǎn)。
2. Flutter Http網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)的區(qū)別和特點(diǎn)
介紹完了Http幾種請(qǐng)求方式,我們看下Flutter中的Http網(wǎng)絡(luò)請(qǐng)求的實(shí)現(xiàn)方式。Flutter的Http網(wǎng)絡(luò)請(qǐng)求的實(shí)現(xiàn)主要分為三種:io.dart里的HttpClient實(shí)現(xiàn)、Dart原生http請(qǐng)求庫實(shí)現(xiàn)、第三方庫實(shí)現(xiàn)。
我們首先看下第一種:io.dart里的HttpClient實(shí)現(xiàn)。
io.dart里的HttpClient實(shí)現(xiàn)的Http網(wǎng)絡(luò)請(qǐng)求主要是實(shí)現(xiàn)了基本的網(wǎng)絡(luò)請(qǐng)求,復(fù)雜一些的網(wǎng)絡(luò)請(qǐng)求還無法完成。例如POST里的其他幾種Body請(qǐng)求體傳輸內(nèi)容類型部分還無法支持,multipart/form-data這個(gè)類型傳輸還不支持。所以如果你的一些Http網(wǎng)絡(luò)請(qǐng)求可以通過io.dart里的HttpClient實(shí)現(xiàn)的話,用這個(gè)也可以完成要求。
那么接下來我們就看下io.dart里的HttpClient實(shí)現(xiàn)的Http網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)步驟。
import 'dart:convert';
import 'dart:io';
class IOHttpUtils {
//創(chuàng)建HttpClient
HttpClient _httpClient = HttpClient();
//要用async關(guān)鍵字異步請(qǐng)求
getHttpClient() async {
_httpClient
.get('https://abc.com', 8090, '/path1')
.then((HttpClientRequest request) {
//在這里可以對(duì)request請(qǐng)求添加headers操作,寫入請(qǐng)求對(duì)象數(shù)據(jù)等等
// Then call close.
return request.close();
}).then((HttpClientResponse response) {
// 處理response響應(yīng)
if (response.statusCode == 200) {
response.transform(utf8.decoder).join().then((String string) {
print(string);
});
} else {
print("error");
}
});
}
getUrlHttpClient() async {
var url = "https://abc.com:8090/path1";
_httpClient.getUrl(Uri.parse(url)).then((HttpClientRequest request) {
// Optionally set up headers...
// Optionally write to the request object...
// Then call close.
return request.close();
}).then((HttpClientResponse response) {
// Process the response.
if (response.statusCode == 200) {
response.transform(utf8.decoder).join().then((String string) {
print(string);
});
} else {
print("error");
}
});
}
//進(jìn)行POST請(qǐng)求
postHttpClient() async {
_httpClient
.post('https://abc.com', 8090, '/path2')
.then((HttpClientRequest request) {
//這里添加POST請(qǐng)求Body的ContentType和內(nèi)容
//這個(gè)是application/json數(shù)據(jù)類型的傳輸方式
request.headers.contentType = ContentType("application", "json");
request.write("{\"name\":\"value1\",\"pwd\":\"value2\"}");
return request.close();
}).then((HttpClientResponse response) {
// Process the response.
if (response.statusCode == 200) {
response.transform(utf8.decoder).join().then((String string) {
print(string);
});
} else {
print("error");
}
});
}
postUrlHttpClient() async {
var url = "https://abc.com:8090/path2";
_httpClient.postUrl(Uri.parse(url)).then((HttpClientRequest request) {
//這里添加POST請(qǐng)求Body的ContentType和內(nèi)容
//這個(gè)是application/x-www-form-urlencoded數(shù)據(jù)類型的傳輸方式
request.headers.contentType =
ContentType("application", "x-www-form-urlencoded");
request.write("name='value1'&pwd='value2'");
return request.close();
}).then((HttpClientResponse response) {
// Process the response.
if (response.statusCode == 200) {
response.transform(utf8.decoder).join().then((String string) {
print(string);
});
} else {
print("error");
}
});
}
///其余的HEAD、PUT、DELETE請(qǐng)求用法類似,大同小異,大家可以自己試一下
///在Widget里請(qǐng)求成功數(shù)據(jù)后,使用setState來更新內(nèi)容和狀態(tài)即可
///setState(() {
/// ...
/// });
}
第二種:Dart原生http請(qǐng)求庫實(shí)現(xiàn)。
這里推薦這種方式使用,畢竟Dart原生的http請(qǐng)求庫支持的Http請(qǐng)求比較全面,比較復(fù)雜的請(qǐng)求都可以實(shí)現(xiàn),如上傳和下載文件等等操作。
Dart目前官方的倉庫里有大量的三方庫和官方庫,引用也非常的方便,Dart PUB官方地址為:https://pub.dartlang.org。
打開后如下圖所示:

使用Dart原生http庫,我們首先需要在Dart PUB或官方Github里把相關(guān)的http庫引用下來。
在Dart PUB里搜索http,便可以查找到我們的http庫,根據(jù)說明進(jìn)行引用和使用即可。
http庫官方Github庫地址為:https://github.com/dart-lang/http

點(diǎn)擊Installing,查看引用方法進(jìn)行引用即可。

在項(xiàng)目的pubspec.yaml配置文件里加入引用:

完畢,這樣就可以在dart文件類里直接import使用了。接下來給一個(gè)完整的使用例子:
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
class DartHttpUtils {
//創(chuàng)建client實(shí)例
var _client = http.Client();
//發(fā)送GET請(qǐng)求
getClient() async {
var url = "https://abc.com:8090/path1?name=abc&pwd=123";
_client.get(url).then((http.Response response) {
//處理響應(yīng)信息
if (response.statusCode == 200) {
print(response.body);
} else {
print('error');
}
});
}
//發(fā)送POST請(qǐng)求,application/x-www-form-urlencoded
postUrlencodedClient() async {
var url = "https://abc.com:8090/path2";
//設(shè)置header
Map<String, String> headersMap = new Map();
headersMap["content-type"] = "application/x-www-form-urlencoded";
//設(shè)置body參數(shù)
Map<String, String> bodyParams = new Map();
bodyParams["name"] = "value1";
bodyParams["pwd"] = "value2";
_client
.post(url, headers: headersMap, body: bodyParams, encoding: Utf8Codec())
.then((http.Response response) {
if (response.statusCode == 200) {
print(response.body);
} else {
print('error');
}
}).catchError((error) {
print('error');
});
}
//發(fā)送POST請(qǐng)求,application/json
postJsonClient() async {
var url = "https://abc.com:8090/path3";
Map<String, String> headersMap = new Map();
headersMap["content-type"] = ContentType.json.toString();
Map<String, String> bodyParams = new Map();
bodyParams["name"] = "value1";
bodyParams["pwd"] = "value2";
_client
.post(url,
headers: headersMap,
body: jsonEncode(bodyParams),
encoding: Utf8Codec())
.then((http.Response response) {
if (response.statusCode == 200) {
print(response.body);
} else {
print('error');
}
}).catchError((error) {
print('error');
});
}
// 發(fā)送POST請(qǐng)求,multipart/form-data
postFormDataClient() async {
var url = "https://abc.com:8090/path4";
var client = new http.MultipartRequest("post", Uri.parse(url));
client.fields["name"] = "value1";
client.fields["pwd"] = "value2";
client.send().then((http.StreamedResponse response) {
if (response.statusCode == 200) {
response.stream.transform(utf8.decoder).join().then((String string) {
print(string);
});
} else {
print('error');
}
}).catchError((error) {
print('error');
});
}
// 發(fā)送POST請(qǐng)求,multipart/form-data,上傳文件
postFileClient() async {
var url = "https://abc.com:8090/path5";
var client = new http.MultipartRequest("post", Uri.parse(url));
http.MultipartFile.fromPath('file', 'sdcard/img.png',
filename: 'img.png', contentType: MediaType('image', 'png'))
.then((http.MultipartFile file) {
client.files.add(file);
client.fields["description"] = "descriptiondescription";
client.send().then((http.StreamedResponse response) {
if (response.statusCode == 200) {
response.stream.transform(utf8.decoder).join().then((String string) {
print(string);
});
} else {
response.stream.transform(utf8.decoder).join().then((String string) {
print(string);
});
}
}).catchError((error) {
print(error);
});
});
}
///其余的HEAD、PUT、DELETE請(qǐng)求用法類似,大同小異,大家可以自己試一下
///在Widget里請(qǐng)求成功數(shù)據(jù)后,使用setState來更新內(nèi)容和狀態(tài)即可
///setState(() {
/// ...
/// });
}
第三種:第三方庫實(shí)現(xiàn)。
Flutter第三方庫有很多可以實(shí)現(xiàn)Http網(wǎng)絡(luò)請(qǐng)求,例如國(guó)內(nèi)開發(fā)者開發(fā)的dio庫,dio支持多個(gè)文件上傳、文件下載、并發(fā)請(qǐng)求等復(fù)雜的操作。在Dart PUB上可以搜索dio。

在項(xiàng)目的pubspec.yaml配置文件里加入引用:
dependencies: dio: ^2.0.14
這樣就可以引用dio的API庫來實(shí)現(xiàn)Http網(wǎng)絡(luò)請(qǐng)求了。給一個(gè)完整的dio用法例子:
import 'dart:io';
import 'package:dio/dio.dart';
class DartHttpUtils {
//配置dio,通過BaseOptions
Dio _dio = Dio(BaseOptions(
baseUrl: "https://abc.com:8090/",
connectTimeout: 5000,
receiveTimeout: 5000));
//dio的GET請(qǐng)求
getDio() async {
var url = "/path1?name=abc&pwd=123";
_dio.get(url).then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
});
}
getUriDio() async {
var url = "/path1?name=abc&pwd=123";
_dio.getUri(Uri.parse(url)).then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
//dio的GET請(qǐng)求,通過queryParameters配置傳遞參數(shù)
getParametersDio() async {
var url = "/path1";
_dio.get(url, queryParameters: {"name": 'abc', "pwd": 123}).then(
(Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
//發(fā)送POST請(qǐng)求,application/x-www-form-urlencoded
postUrlencodedDio() async {
var url = "/path2";
_dio
.post(url,
data: {"name": 'value1', "pwd": 123},
options: Options(
contentType:
ContentType.parse("application/x-www-form-urlencoded")))
.then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
//發(fā)送POST請(qǐng)求,application/json
postJsonDio() async {
var url = "/path3";
_dio
.post(url,
data: {"name": 'value1', "pwd": 123},
options: Options(contentType: ContentType.json))
.then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
// 發(fā)送POST請(qǐng)求,multipart/form-data
postFormDataDio() async {
var url = "/path4";
FormData _formData = FormData.from({
"name": "value1",
"pwd": 123,
});
_dio.post(url, data: _formData).then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
// 發(fā)送POST請(qǐng)求,multipart/form-data,上傳文件
postFileDio() async {
var url = "/path5";
FormData _formData = FormData.from({
"description": "descriptiondescription",
"file": UploadFileInfo(File("./example/upload.txt"), "upload.txt")
});
_dio.post(url, data: _formData).then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
//dio下載文件
downloadFileDio() {
var urlPath = "https://abc.com:8090/";
var savePath = "./abc.html";
_dio.download(urlPath, savePath).then((Response response) {
if (response.statusCode == 200) {
print(response.data.toString());
}
}).catchError((error) {
print(error.toString());
});
}
///其余的HEAD、PUT、DELETE請(qǐng)求用法類似,大同小異,大家可以自己試一下
///在Widget里請(qǐng)求成功數(shù)據(jù)后,使用setState來更新內(nèi)容和狀態(tài)即可
///setState(() {
/// ...
/// });
}
好了,F(xiàn)lutter的Http網(wǎng)絡(luò)請(qǐng)求詳解就為大家講解到這里。
到此這篇關(guān)于Flutter Http網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)詳解的文章就介紹到這了,更多相關(guān)Flutter Http網(wǎng)絡(luò)請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)圖片加載進(jìn)度提示
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)圖片加載進(jìn)度提示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
android圖像繪制(四)自定義一個(gè)SurfaceView控件
自定義控件(類似按鈕等)的使用,自定義一個(gè)SurfaceView。如某一塊的動(dòng)態(tài)圖(自定義相應(yīng)),或者類似UC瀏覽器下面的工具欄,感興趣的朋友可以了解下2013-01-01
Android編程學(xué)習(xí)之抽象類AbsListView用法實(shí)例分析
這篇文章主要介紹了Android編程學(xué)習(xí)之抽象類AbsListView用法,較為詳細(xì)的分析了抽象類AbsListView的功能、結(jié)構(gòu)、定義及使用注意事項(xiàng)等,需要的朋友可以參考下2015-10-10
Android studio刪除Android項(xiàng)目方法
在本篇內(nèi)容里我們給大家介紹的是關(guān)于Android studio刪除Android項(xiàng)目方法和步驟,需要的可以學(xué)習(xí)下。2018-12-12
詳解ListView中多種item的實(shí)現(xiàn)方式
這篇文章主要給大家介紹了關(guān)于ListView中多種item的實(shí)現(xiàn)方式,文中通過示例代碼介紹的很詳細(xì),有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-12-12
WindowManagerService服務(wù)是如何以堆棧的形式來組織窗口
我們知道,在Android系統(tǒng)中,Activity是以堆棧的形式組織在ActivityManagerService服務(wù)中的;在本文中,我們就詳細(xì)分析WindowManagerService服務(wù)是如何以堆棧的形式來組織窗口的2013-01-01
android6.0權(quán)限動(dòng)態(tài)申請(qǐng)框架permissiondispatcher的方法
下面小編就為大家分享一篇android6.0權(quán)限動(dòng)態(tài)申請(qǐng)框架permissiondispatcher的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01
Android中Fragment多層嵌套時(shí)onActivityResult無法正確回調(diào)問題的解決方法
這篇文章主要介紹了Android中Fragment多層嵌套時(shí)onActivityResult無法正確回調(diào)問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
基于android樣式與主題(style&theme)的詳解
本篇文章是對(duì)android中的樣式與主題(style&theme)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06

