前言
我們?cè)陂_(kāi)發(fā)中,會(huì)面臨要從服務(wù)器請(qǐng)求數(shù)據(jù)况凉,然后解析服務(wù)器過(guò)來(lái)的json數(shù)據(jù)进鸠,這個(gè)在android中,都有相應(yīng)的的封裝好的很好的插件可以做這樣的事情碱屁,請(qǐng)求數(shù)據(jù)有okHttp
磷脯,解析有GSON
。那么在flutter中呢娩脾,對(duì)應(yīng)的可以是什么呢赵誓,我目前請(qǐng)求數(shù)據(jù)使用的是dio
,解析使用的是json_serializable
柿赊,下面是一個(gè)簡(jiǎn)單的例子
實(shí)踐
一俩功、集成插件
在pubspec.yaml
文件中添加dio
和json_serializable
的相關(guān)插件,這里我貼上我的:
dependencies:
flutter:
sdk: flutter
dio: ^3.0.8 #網(wǎng)絡(luò)請(qǐng)求
json_annotation: ^3.0.1
dev_dependencies:
flutter_test:
sdk: flutter
#這兩個(gè)是dev的碰声,不要放到上面去了哦
build_runner: ^1.7.3
json_serializable: ^3.2.5
二诡蜓、封裝網(wǎng)絡(luò)請(qǐng)求
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:the_first_one/model/Api.dart';
//要查網(wǎng)絡(luò)請(qǐng)求的日志可以使用過(guò)濾<net>
class NetUtil {
static const String GET = "get";
static const String POST = "post";
//get請(qǐng)求
static void get(String url, Function callBack,
{Map<String, String> params, Function errorCallBack}) async {
_request(Api.BaseUrl + url, callBack,
method: GET, params: params, errorCallBack: errorCallBack);
}
//post請(qǐng)求
static void post(String url, Function callBack,
{Map<String, String> params, Function errorCallBack}) async {
_request(url, callBack,
method: POST, params: params, errorCallBack: errorCallBack);
}
//具體的還是要看返回?cái)?shù)據(jù)的基本結(jié)構(gòu)
//公共代碼部分
static void _request(String url, Function callBack,
{String method,
Map<String, String> params,
Function errorCallBack}) async {
print("<net> url :<" + method + ">" + url);
if (params != null && params.isNotEmpty) {
print("<net> params :" + params.toString());
}
String errorMsg = "";
int statusCode;
try {
Response response;
if (method == GET) {
//組合GET請(qǐng)求的參數(shù)
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 (params != null && params.isNotEmpty) {
response = await Dio().post(url, data: params);
} else {
response = await Dio().post(url);
}
}
statusCode = response.statusCode;
//處理錯(cuò)誤部分
if (statusCode < 0) {
errorMsg = "網(wǎng)絡(luò)請(qǐng)求錯(cuò)誤,狀態(tài)碼:" + statusCode.toString();
_handError(errorCallBack, errorMsg);
return;
}
if (callBack != null) {
callBack(response.data["data"]);
print("<net> response data:" + response.data["data"]);
}
} catch (exception) {
_handError(errorCallBack, exception.toString());
}
}
//處理異常
static void _handError(Function errorCallback, String errorMsg) {
if (errorCallback != null) {
errorCallback(errorMsg);
}
print("<net> errorMsg :" + errorMsg);
}
}
以上的封裝,主要基于返回的數(shù)據(jù)結(jié)構(gòu)奥邮,我造了個(gè)數(shù)據(jù)万牺,大概長(zhǎng)下面這樣:
在這里罗珍,我使用mocky來(lái)創(chuàng)建API
{
"statusCode": 1,
"data": {
"name": "zoe",
"email": "zoey@qq.com",
"pics": [
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1534747043&di=2e3d49c934bb603bcf3f2fe8befd94fc&imgtype=jpg&er=1&src=http%3A%2F%2Fimg0.pconline.com.cn%2Fpconline%2F1309%2F30%2F3571757_9.jpg",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1534152325030&di=d1d8493bfe1d5f7a9715b6db8ef3d29d&imgtype=0&src=http%3A%2F%2Fc1.cdn.goumin.com%2Fcms%2Fdetail%2Fday_171101%2F20171101_140dd79.png",
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1534152325029&di=684aa3a8225a7828ba6b04c8ea4bccd3&imgtype=0&src=http%3A%2F%2Fimgq.duitang.com%2Fuploads%2Fblog%2F201505%2F15%2F20150515014759_Qz5Tw.thumb.700_0.jpeg"
]
}
}
三、創(chuàng)建model
為了便利的使用json_serializable
庫(kù)脚粟,我們使用這位大牛的這個(gè)小工具:
將右側(cè)框內(nèi)轉(zhuǎn)換過(guò)的內(nèi)容復(fù)制下來(lái)覆旱,在自己項(xiàng)目中創(chuàng)建user.dart文件,將你復(fù)制的內(nèi)容粘貼進(jìn)去核无。然后你會(huì)看到類(lèi)中一些地方會(huì)飄紅線扣唱,這是正常的哈,執(zhí)行下面的命令后就會(huì)好了:
這個(gè)時(shí)候团南,你在項(xiàng)目根目錄下輸入命令:flutter packages pub run build_runner build
(這個(gè)命令需要每次在model類(lèi)中進(jìn)行更改時(shí)都要手動(dòng)運(yùn)行構(gòu)建噪沙。也可以使用命令:flutter packages pub run build_runner watch
,它會(huì)監(jiān)視我們項(xiàng)目中文件的變化,并在需要時(shí)自動(dòng)構(gòu)建必要的文件,只需啟動(dòng)一次觀察器吐根,然后并讓它在后臺(tái)運(yùn)行正歼,這是安全的。個(gè)人推薦后面這個(gè)命令哈)拷橘,完成之后會(huì)在user.dart
同級(jí)目錄下局义,自動(dòng)創(chuàng)建一個(gè)名為user.g.dart
的文件:
有時(shí)候也會(huì)有些很詭異的事情出現(xiàn),比如不管怎么輸命令冗疮,最后就是生成不了g.dart文件萄唇,這時(shí)候可以使用命令flutter packages pub run build_runner build --delete-conflicting-outputs
,將所有的都刪除术幔,重新生成另萤,一般都會(huì)變好,我也是不曉得為什么
以下是日志(其中會(huì)有一些警告信息诅挑,比如Unable to resolve asset ID for "dart:ui"
四敞,在我看來(lái),好像不影響哈拔妥,暫時(shí)可以不用管):
F:\FlutterSpace\flutter_the_first_demo>flutter packages pub run build_runner build
[INFO] Generating build script...
[INFO] Generating build script completed, took 465ms
[INFO] Initializing inputs
[INFO] Reading cached asset graph...
[WARNING] Throwing away cached asset graph due to version mismatch.
[INFO] Reading cached asset graph completed, took 57ms
[INFO] Building new asset graph...
[INFO] Building new asset graph completed, took 522ms
[INFO] Checking for unexpected pre-existing outputs....
[INFO] Checking for unexpected pre-existing outputs. completed, took 2ms
[INFO] Running build...
[INFO] 2.6s elapsed, 3/65 actions completed.
[INFO] 3.6s elapsed, 4/65 actions completed.
[INFO] 4.7s elapsed, 4/65 actions completed.
[INFO] 5.7s elapsed, 4/65 actions completed.
[INFO] 6.8s elapsed, 4/65 actions completed.
[INFO] 7.9s elapsed, 4/65 actions completed.
[INFO] 9.0s elapsed, 4/65 actions completed.
[INFO] 10.0s elapsed, 4/65 actions completed.
[SEVERE] json_serializable on lib/components/BottomComponent2.dart:
Unable to resolve asset ID for "dart:ui"
[INFO] 17.0s elapsed, 56/65 actions completed.
[INFO] Running build completed, took 17.7s
[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 52ms
[SEVERE] Failed after 17.8s
pub finished with exit code 1
使用
import 'package:flutter/material.dart';
import 'package:the_first_one/model/user.dart';
import 'package:the_first_one/utils/NetUtil.dart';
import 'package:the_first_one/components/LoadingComponent.dart';
class JsonSeralizablePage extends StatefulWidget {
@override
_JsonSeralizablePageState createState() => _JsonSeralizablePageState();
}
class _JsonSeralizablePageState extends State<JsonSeralizablePage> {
String name = "";
String email = "";
List<String> picList = <String>[];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("JSON"),
),
body: (picList != null && picList.length == 0)
? LoadingComponent()
: SingleChildScrollView(
child: Column(
children: <Widget>[
Text(
name,
style: TextStyle(color: Colors.black, fontSize: 20.0),
),
SizedBox(height: 20.0),
Text(
email,
style: TextStyle(color: Colors.black, fontSize: 15.0),
),
SizedBox(height: 20.0),
SizedBox(
height: 250.0 * picList.length,
child: ListView.builder(
physics: ClampingScrollPhysics(),
itemCount: picList != null && picList.length > 0
? picList.length
: 0,
itemBuilder: (BuildContext context, int index) {
return picList != null && picList.length > 0
? Image(
image: NetworkImage(picList[index]),
width: 400.0,
height: 250.0,
fit: BoxFit.cover)
: Text("no pics");
},
),
),
],
),
),
);
}
@override
void initState() {
super.initState();
getContent();
}
//獲取網(wǎng)絡(luò)數(shù)據(jù)
void getContent() {
NetUtil.get("http://www.mocky.io/v2/5b7143ae3200001402f36c46", (data) {
User user = User.fromJson(data);
setState(() {
name = user.name;
email = user.email;
picList = user.pics;
});
}, errorCallBack: (errorMsg) {
print("error:" + errorMsg);
});
}
}
效果:
寫(xiě)在最后
本人剛?cè)腴T(mén)目养,所學(xué)尚淺,如有不當(dāng)或不足之處毒嫡,希望能得到指點(diǎn)