* 
Flutter网络请求使用的是Dio。Dio是一个强大易用的dart http请求库,支持Restful 
API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载…
 * 
Flutter json数据解析是使用了json_serializable 
package包。它是一个自动化源代码生成器,可以为我们生成JSON序列化模板。由于序列化代码不再由我们手写和维护,我们将运行时产生JSON序列化异常的风险降至最低。
 * 
Flutter网络请求数据并且展示效果图:
 * 
数据接口
 数据是使用的聚合数据的API,影讯API合集,大家可以注册个账号,申请使用一下,像这样
 * 
添加依赖
 在pubspec.yaml文件中添加所需要的第三方依赖库
 environment: sdk: ">=2.1.0 <3.0.0" dependencies: flutter: sdk: flutter 
json_annotation: ^2.0.0 connectivity: ^0.4.2 dio: ^2.0.15 event_bus: ^1.0.3 # 
The following adds the Cupertino Icons font to your application. # Use with the 
CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 
dev_dependencies: flutter_test: sdk: flutter 
 * 
网络请求过程分析
 static netFetch(url,params,Map<String,String> header,Options option,{noTip = 
false}) async { //获取网络的连接状态,如果没有连接网络,返回NETWORK_ERROR var connectivityResult = 
await (new Connectivity().checkConnectivity()); if(connectivityResult == 
ConnectivityResult.none) { return new 
ResultData(Code.errorHandleFunction(Code.NETWORK_ERROR, "", 
noTip),false,Code.NETWORK_ERROR); } //请求头存放集合 Map<String,String> headers = new 
HashMap(); if(header != null) { headers.addAll(header); } //option存放请求的一些配置信息 
if(option != null) { option.headers = headers; }else { //get请求 option = new 
Options(method:'get'); option.headers = headers; } //超时时间15000ms 
option.connectTimeout = 15000; //创建dio对象 Dio dio = new Dio(); Response 
response; try{ //执行网络请求,await和async配合使用,表示这是一个异步耗时操作 //执行结果不会立马返回。 response = 
await dio.request(url,data: params,options: option); }on DioError catch(e) { 
//异常处理 .... return new 
ResultData(Code.errorHandleFunction(errorResponse.statusCode, e.message, 
noTip), false, errorResponse.statusCode); } try{ if(response.statusCode == 200 
|| response.statusCode == 201) { //网络请求成功 return await new 
ResultData(response.data, true, Code.SUCCESS,headers: response.headers); } 
}catch(e) { //异常处理 print('返回参数' + e.toString() + url); return new 
ResultData(response.data, false, response.statusCode,headers: 
response.headers); } return new 
ResultData(Code.errorHandleFunction(response.statusCode, "", noTip), false, 
response.statusCode); } 
这个是最底层类封装了一个静态的请求方法,直接调用dio的request方法进行网路请求,很简单。
 //如果这个是耗时方法,就会用async标记,耗时操作用await标记,表示是一个异步操作。 static getTodayFilmListDao() 
async { //获取请求的url String url = Address.getTodayFilmList(); 
//调用上面封装的网络请求方法进行网络请求 var res = await HttpManager.netFetch(url, null, null, 
null); if(res != null && res.result) { var data = res.data; if(data == null || 
data.length == 0) { return await new DataResult([],true); } //网络请求成功,进行数据解析 var 
response = TodayFilmResponse.fromJson(data); //返回数据 return await new 
DataResult(response.result,true); }else { return await new 
DataResult(null,false); } } 
获取url方法很简单,就是字符串拼接了一下
 static getTodayFilmList() { return 
"${host}movie/movies.today?cityid=1&dtype=&key=713a408e855352d913806ef1e3ce3c33"; 
} 
 * 
下面分析一下json数据解析过程。
 如上所说,json解析使用的是json_serializable package包。它是一个自动化源代码生成器,可以为我们生成JSON序列化模板。
 网络请求获取到的json数据是这样的
 { "movieId":"135808", "movieName":"新喜剧之王", 
"pic_url":"http:\/\/img5.mtime.cn\/mt\/2019\/02\/02\/113216.53857992_182X243X4.jpg" 
}, 
TodayFilmBean类
 //TodayFilmBean.g.dart将在我们运行生成命令之后自动生成 part 'TodayFilmBean.g.dart'; 
//这个标注是告诉生成器,这个类是要生成的Model类 @JsonSerializable() class TodayFilmBean{ String 
movieId; String movieName; String pic_url; //构造函数 
TodayFilmBean(this.movieId,this.movieName,this.pic_url); //json转换为bean对象 
factory TodayFilmBean.fromJson(Map<String,dynamic> json) => 
_$todayFilmBeanFromJson(json); //bean对象转换为json Map<String,dynamic> toJson() => 
_$todayFilmBeanToJson(this); } 
生成的TodayFilmBean.g.dart类是这样的
 part of 'TodayFilmBean.dart'; //json转换为bean对象 TodayFilmBean 
_$todayFilmBeanFromJson(Map<String,dynamic> json) { return 
TodayFilmBean(json['movieId'] as String,json['movieName'] as String, 
json['pic_url'] as String); } //bean对象转换为json Map<String,dynamic> 
_$todayFilmBeanToJson(TodayFilmBean instance) => <String,dynamic> { 'movieId': 
instance.movieId, 'movieName': instance.movieName, 'pic_url':instance.pic_url };
有两种运行代码生成器的方法:
 1.一次性生成
 通过在我们的项目根目录下运行flutter packages pub run build_runner 
build,我们可以在需要时为我们的model生成json序列化代码。这触发了一次性构建,它通过我们的源文件,挑选相关的并为它们生成必要的序列化代码。
虽然这非常方便,但如果我们不需要每次在model类中进行更改时都要手动运行构建命令的话会更好。
2.持续生成
 使用_watcher_可以使我们的源代码生成的过程更加方便。它会监视我们项目中文件的变化,并且在需要时自动构建必要的文件。我们可以通过flutter 
packages pub run build_runner watch 在项目根目录下运行来启动_watcher_。
只需启动一次观察器,然后并让它在后台运行,这是安全的。
执行序列化只需执行
 //把json数据转化为了bean对象 var filmBean = TodayFilmBean.fromJson(json); 
 * 
使用GridView最终展示结果
 DataResult dataResult; List<TodayFilmBean> mData = []; 
//当StatefulWiget被嵌入此view树中,就会为此widget创建State对象 
//当State对象被创建了,frameWork就会调用initState()方法 @override void initState() { //初始化数据 
getTodayFilm(); super.initState(); } void getTodayFilm() async { 
//这是一个异步操作,结果返回有一定延迟 dataResult = await TodayDao.getTodayFilmListDao(); 
//调用setState方法会通知framework控件状态有变化,它会立马触发 //State的build方法更新widget状态 setState(() 
{ mData = dataResult.data; }); } 
上面是初始化网络请求,在请求到数据后,调用setState刷新UI
 //State的build方法,调用setState方法后,此方法就会被触发 //用来刷新UI @override Widget 
build(BuildContext context) { return Scaffold( appBar: AppBar( title: 
Text(widget.title), ), //如果mData.length == 0,展示一个loading框,否则展示数据 body: 
mData.length == 0 ? new Center(child: new CircularProgressIndicator()): 
//创建GridView对象 new GridView.builder( gridDelegate: 
SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, //每行2个 
mainAxisSpacing: 1.0, //主轴(竖直)方向间距 crossAxisSpacing: 1.0, //纵轴(水平)方向间距 
childAspectRatio: 0.7 //纵轴缩放比例 ), //item数量 itemCount:mData.length, //创建每个item 
itemBuilder: (BuildContext context,int index) { return _getWidget(index); }), 
); } _getWidget(int index) { //添加要展示的item内容 return new Column( children: 
<Widget>[ new Expanded(child: new CardItem(color: Colors.black12,child: 
_getChild(index)),flex: 8,), //显示网络请求文本 new Expanded(child: new 
Text(mData[index].movieName, textAlign: TextAlign.end, maxLines: 1, ), flex:1) 
]); } _getChild(int i) { return new Padding(padding: new EdgeInsets.all(1.0), 
//显示网络请求的图片 child: new Image(image: NetworkImage(mData[i].pic_url))); } 
一个自定义的CardItem
 class CardItem extends StatelessWidget{ final Widget child; final EdgeInsets 
margin; final Color color; final RoundedRectangleBorder shape; final double 
elevation; CardItem({@required this.color,this.child,this.elevation = 
5.0,this.shape,this.margin}); @override Widget build(BuildContext context) { 
EdgeInsets margin = this.margin; RoundedRectangleBorder shape = this.shape; 
Color color = this.color; margin ??= EdgeInsets.only(left: 2.0,top: 2.0,right: 
2.0,bottom: 2.0); shape ??= new RoundedRectangleBorder(borderRadius: new 
BorderRadius.all(Radius.circular(4.0))); color ??= new Color(0xffeeff); return 
new Card(elevation: elevation,shape: shape,color: color,margin: margin,child: 
child,); } } 
好了,Flutter网络请求并且展示数据就这样实现的。
 最后附上demo地址:https://github.com/xinhuashi/flutter_http_demo.git 
<https://github.com/xinhuashi/flutter_http_demo.git>
热门工具 换一换