Flutter開發(fā)對(duì)于Http對(duì)于網(wǎng)絡(luò)請(qǐng)求的封裝及Json數(shù)據(jù)處理

目錄
前言
????自谷歌在2018大會(huì)公布Beta1也有了一段時(shí)間,這段時(shí)間以來(lái)flutter也越來(lái)越熱。這段時(shí)間我也對(duì)Flutter進(jìn)行了一些學(xué)習(xí),今天準(zhǔn)備把一些學(xué)的內(nèi)容進(jìn)行整理,一是為了梳理下學(xué)習(xí)的一些知識(shí)節(jié)點(diǎn),二是通過一些封裝整理,方便后期如過需要使用flutter開發(fā)可以快速搭建基礎(chǔ)組件進(jìn)行開發(fā)。
目錄結(jié)構(gòu)

對(duì)于項(xiàng)目,我做了如上一些目錄區(qū)分:
dao:主要做一些接口調(diào)用及邏輯處理。
exts:做一些擴(kuò)展累比如callback等。
http:對(duì)網(wǎng)絡(luò)請(qǐng)求dio的再次封裝。
json:對(duì)數(shù)據(jù)json解析接口定義。
model:對(duì)bean類的定義。
viewmodel:對(duì)頁(yè)面數(shù)據(jù)集合類。
這篇文章中,主要是對(duì)http和json解析兩塊的封裝使用。
HTTP
Dio
????dio作為一個(gè)強(qiáng)大的Drat Http開源請(qǐng)求庫(kù),我們已經(jīng)可以很方便的使用它進(jìn)行一些網(wǎng)絡(luò)請(qǐng)求,但我對(duì)它進(jìn)行了二次封裝,主要是一些配置的統(tǒng)一設(shè)置和一些邏輯的統(tǒng)一處理。

????我們先來(lái)看DioUtil類,這里我采用單例模式來(lái)創(chuàng)建dio對(duì)象,并默認(rèn)設(shè)置了baseurl,也可以在項(xiàng)目啟動(dòng)使用通過init()方法設(shè)置Options來(lái)初始化配置。
http

????在HttpUtil中最主要是對(duì)dio的request()方法進(jìn)行封裝,提供了統(tǒng)一的配置和處理。
其中:
//可以通過mheaders配置公共head
mheaders = new Map<String, dynamic>();
if (handers != null) {
mheaders.addAll(handers);
}
options.headers = mheaders;
????可以通過mheaders配置統(tǒng)一的head及組合由方法傳入的handers組成最終的請(qǐng)求head。
static String errorNet = "{\"code\":19,\"msg\":\"網(wǎng)絡(luò)錯(cuò)誤,請(qǐng)檢查網(wǎng)絡(luò)情況\"}";
ConnectUtil.isConnect((val) async {
if (val) {
...
} else {
callback(19, errorNet);
}
}
????在真正請(qǐng)求開始前通過ConnectUtil做網(wǎng)絡(luò)情況判斷,因?yàn)楫惒剑酝ㄟ^回調(diào)方式處理并做預(yù)定格式返回錯(cuò)誤。(網(wǎng)絡(luò)情況判斷通過第三方connectivity框架實(shí)現(xiàn))
static String errorMsg = "{\"code\":0,\"msg\":\"數(shù)據(jù)訪問錯(cuò)誤,請(qǐng)檢查\"}";
final code = response.statusCode;
final strJson = response.data.toString();
LogUtil.d("HttpUtil", "code:" + code.toString() + " outdata:" + data);
if (strJson != null && strJson != "") {
if (code != 200) {
callback(0, errorMsg);
} else {
callback(code, strJson);
}
} else {
callback(0, errorMsg);
}
????請(qǐng)求返回后,如果請(qǐng)求錯(cuò)誤,也同樣做了統(tǒng)一的錯(cuò)誤格式返回,同時(shí)也可以在這里做統(tǒng)一的錯(cuò)誤邏輯處理。

????同時(shí)HttpUtil提供get和post兩個(gè)簡(jiǎn)單的api進(jìn)行及少量入?yún)⒓纯蛇M(jìn)行網(wǎng)絡(luò)請(qǐng)求。
JSON
????因?yàn)镕lutter中是禁止反射的,所為我們也就不能使用GSON / Jackson之類的進(jìn)行序列化和反序列化。然而我們現(xiàn)在很多時(shí)間接口請(qǐng)求都是以json格式進(jìn)行返回的。那么又怎么樣實(shí)現(xiàn)從json到model到轉(zhuǎn)換呢。
????在項(xiàng)目中我通過我通過dart:convert中內(nèi)置的JSON解碼器,它將原始JSON字符串傳遞給JSON.decode() 方法,然后在返回的Map<String, dynamic>中查找所需的值,通過手動(dòng)的方式進(jìn)行實(shí)現(xiàn)。

????首先通過JsonModel設(shè)置抽象方法bind(),然后讓所有model類都繼承JsonModel類并實(shí)現(xiàn)bind()方法,并且bing方法的參數(shù)為Map類型,所以每個(gè)model方法只需先實(shí)現(xiàn)中通過map獲取所需的屬性值即可。如下面UserModel類所示。

????那我們又在什么時(shí)候吧json轉(zhuǎn)換成map的呢?入下圖,我創(chuàng)建了JsonViewModel類來(lái)進(jìn)行此項(xiàng)操作。


????在JsonViewModel中通過fromJson()方法傳入json字符串,然后通過json.decode(data)方法解析成map。
????因?yàn)镴sonViewModel也同樣繼承了JsonModel。所以我們可以bind(jMap["data"]);的形式調(diào)研bind方法并傳入對(duì)于數(shù)據(jù),并且在JsonViewModel的子類中做具體處理。
????要注意的是,我們預(yù)先把返回的json格式定義成了code,msg,data的形式,如果預(yù)定義的返回格式有修改可以在這邊進(jìn)行調(diào)整。

????至此,我們只需要在請(qǐng)求返回時(shí)候?qū)嵗瘜?duì)應(yīng)的viewmodel類,并調(diào)用fromJson()方法就可以得到對(duì)于的數(shù)據(jù)實(shí)體了。
GitHub
要看源碼點(diǎn)這里