首發於個人公衆號html
Flutter中消息傳遞java
網絡請求到數據解析是一個app必不可少的流程之一,在flutter官網中目前主要是介紹 自帶的Http請求+Json解析 可是也推薦了更好的網路請求到組合的方式 dio 和 json_serializable,本篇文章主要介紹這兩個方式的使用,源碼在結尾android
本文同步更新於個人gitpage xsfelvis.github.io/2018/12/08/…git
package地址 pub.flutter-io.cn/packages/di…, 添加依賴github
dependencies: dio: ^1.0.9json
支持了支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時等 Performing a GET
request: 簡單的使用以下緩存
Response response;
response=await dio.get("/test?id=12&name=wendu")
print(response.data.toString());
// Optionally the request above could also be done as
response=await dio.get("/test",data:{"id":12,"name":"wendu"})
print(response.data.toString());
複製代碼
Performing a POST
request:網絡
response=await dio.post("/test",data:{"id":12,"name":"wendu"})
複製代碼
Performing multiple concurrent requests:app
response= await Future.wait([dio.post("/info"),dio.get("/token")]);
複製代碼
Downloading a file:async
response=await dio.download("https://www.google.cn/","./xx.html")
複製代碼
Sending FormData:
FormData formData = new FormData.from({
"name": "wendux",
"age": 25,
});
response = await dio.post("/info", data: formData)
複製代碼
Uploading multiple files to server by FormData:
FormData formData = new FormData.from({
"name": "wendux",
"age": 25,
"file1": new UploadFileInfo(new File("./upload.txt"), "upload1.txt"),
// upload with bytes (List<int>)
"file2": new UploadFileInfo.fromBytes(utf8.encode("hello world"),"word.txt"),
// Pass multiple files within an Array
"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)
複製代碼
而且因爲flutter原生的http庫不支持charles抓包,這個庫可使用設置代理來達到抓包的目的,ip本身替換
dio.onHttpClientCreate = (HttpClient client) {
client.findProxy = (uri) {
//proxy all request to localhost:8888
return "PROXY yourIP:yourPort";
};
};
複製代碼
這樣就可抓包了。
簡單封裝使咱們更加容易的使用,核心代碼以下
void _request(String url, Function callBack, {String method, Map<String, String> params, Function errorCallBack}) async {
// dio.onHttpClientCreate = (HttpClient client) {
// client.findProxy = (uri) {
// //proxy all request to localhost:8888
// return "PROXY 172.23.235.153:8888";
// };
// };
String errorMsg = "";
int statusCode;
try {
Response response;
if (method == GET) {
if (params != null && params.isNotEmpty) {
StringBuffer sb = new StringBuffer("?");
params.forEach((key, value) {
sb.write("$key" + "=" + "$value" + "&");
});
String paramStr = sb.toString();
paramStr = paramStr.substring(0, paramStr.length - 1);
url += paramStr;
}
response = await dio.get(url);
} else if (method == POST) {
if (params != null && params.isNotEmpty) {
response = await dio.post(url, data: params);
} else {
response = await dio.post(url);
}
}
statusCode = response.statusCode;
if (statusCode < 0) {
errorMsg = "網絡請求錯誤,狀態碼:" + statusCode.toString();
_handError(errorCallBack, errorMsg);
return;
}
if (callBack != null) {
String res2Json = json.encode(response.data);
Map<String,dynamic> map=json.decode(res2Json);
callBack(map["data"]);
}
} catch (exception) {
_handError(errorCallBack, exception.toString());
}
}
複製代碼
詳細的能夠參考源碼github.com/xsfelvis/le…
使用以下
HttpCore.instance.get(Api.HOME_BANNER, (data) {
List<BannerData> banners = getBannersList(data);
setState(() {
slideData = banners;
});
}, errorCallBack: (errorMsg) {
print("error:" + errorMsg);
return null;
});
複製代碼
在封裝網絡庫的的時候發現 底層 response.data['data']時候當是一個jsonarray時候居然沒法直接取出'data',"Stirng not subType of Index "錯誤,緣由是 此時拿到的不是一個json數據,沒有雙引號的假json數據,可是在jsonobject卻能夠,解決以下
if (callBack != null) {
String res2Json = json.encode(response.data);
Map<String,dynamic> map=json.decode(res2Json);
callBack(map["data"]);
}
複製代碼
package地址 pub.flutter-io.cn/packages/js… 添加依賴
dependencies: json_serializable: ^2.0.0 dev_dependencies build_runner: ^1.1.2 json_serializable: ^2.0.0
這個是個好東西,以前的至關於json數據一個個經過key解出來(關於自帶的json解析能夠參考 juejin.im/post/5b5d78…),不只耗時並且容易出錯,json_serializable 讓咱們直接反序列化成對象直接使用相似於Gson,並且還提供了一個工具來自動幫助咱們生成代碼,簡單快捷並且不容易出錯
如下面json爲例
{
"data":{
"curPage":2,
"datas":[
{
"apkLink":"",
"author":"鴻洋",
"chapterId":410,
"chapterName":"玉剛說",
"collect":false,
"courseId":13,
"desc":"",
"envelopePic":"",
"fresh":false,
"id":7604,
"link":"https://mp.weixin.qq.com/s/cCZKmqKrdCn63eWTbOuANw",
"niceDate":"2018-12-03",
"origin":"",
"projectLink":"",
"publishTime":1543830090000,
"superChapterId":408,
"superChapterName":"公衆號",
"tags":[
{
"name":"公衆號",
"url":"/wxarticle/list/410/1"
}
],
"title":"在 Retrofit 和 OkHttp 中使用網絡緩存,提升訪問效率",
"type":0,
"userId":-1,
"visible":1,
"zan":0
},
{
"apkLink":"",
"author":"鴻洋",
"chapterId":408,
"chapterName":"鴻洋",
"collect":false,
"courseId":13,
"desc":"",
"envelopePic":"",
"fresh":false,
"id":7605,
"link":"https://mp.weixin.qq.com/s/r3AWeYafyMEc1-g8BWEHBg",
"niceDate":"2018-12-03",
"origin":"",
"projectLink":"",
"publishTime":1543766400000,
"superChapterId":408,
"superChapterName":"公衆號",
"tags":[
{
"name":"公衆號",
"url":"/wxarticle/list/408/1"
}
],
"title":"非 UI 線程能調用 View.invalidate()?",
"type":0,
"userId":-1,
"visible":1,
"zan":0
}
],
"offset":20,
"over":false,
"pageCount":289,
"size":20,
"total":5779
},
"errorCode":0,
"errorMsg":""
}
複製代碼
爲例,咱們首先找到實際數據信息,由於異errorcode 之類的處理已在上面的封裝網絡請求中處理了,這裏須要關注 實際內容傳遞者 「data」裏面的數據,將上面這個data裏面的jsonObject,從data 這個key後面包括大括號一塊兒複製到上面的代碼生成工具網頁裏面,截圖以下
而後當前項目的目錄下運行 flutter packages pub run build_runner build
然就能夠獲得news.g.dart文件
而後在使用中經過獲取對象屬性的方式就能夠直接拿到咱們關注的字段了
// 獲取News數據
void _getNewsList(int curpage) {
var url = Api.HOME_ARTICLE + curpage.toString() + "/json";
HttpCore.instance.get(url, (data) {
News news = News.fromJson(data);
List<Datas> newsDatas = news.datas;
setState(() {
listData = newsDatas;
});
});
}
複製代碼
咱們能夠經過JsonKey自定義參數進行註釋並自定義參數來自定義各個字段。例如:是否容許字段爲空等。注意,這裏不加任何JsonKey默認容許空json字段。 好比解析字段有個橫線,而dart中只容許字母數字下劃線做爲變量名。因此咱們必須對它進行特殊處理。@JsonKey(name="off-set")來解析map,一般自動生成代碼的工具已經能夠幫助咱們解決了
@JsonKey(name: 'off-set')
int offset;
複製代碼
效果以下圖
接口來自 玩Android的開放接口
代碼在 learnflutter 的demo3
歡迎關注個人公衆號,一塊兒學習,共同提升~
複製代碼