移动端UI展示最常见的展示形式莫过于列表,Android中使用ListView/Recyclerview,iOS也有UIListView,都可以实现列表展示。Flutter作为兼容Android和iOS的移动UI框架,自然也有实现此功能的组件,即ListView。

本文数据采用爬虫爬取华尔街见闻全球资讯,然后采用GraphQL接口请求数据。显示效果如下


<>实现

* 创建ListView 及每个显示的item
* 网络请求
* json解析
* 数据显示
<>创建ListView及每个显示的item

使用如下代码创建一个ListView
其中listData 为列表加载的数据,因先初始化下 List listData = [];
ListView getListView() => new ListView.builder( itemCount: (listData== null)
? 0 : listData.length, itemBuilder: (BuildContext context, int position) {
return getItem(position); });
上面的getItem方法即为列表item的布局,使用Column与Row实现垂直和水平布局,核心代码如下:
new Padding( padding: new EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0), child:
new Column( children: <Widget>[ new Row( crossAxisAlignment:
CrossAxisAlignment.start, //纵向对齐方式:起始边对齐 mainAxisSize: MainAxisSize.max,
children: <Widget>[ new Expanded( child: Container( height: 95.0, child:
getImage(data.articleThumbnail),//封面 alignment: FractionalOffset.center, ),
flex: 1, ), new Expanded( child: Container( height: 95.0, margin: new
EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 0.0), child: new Column( crossAxisAlignment:
CrossAxisAlignment.start, children: <Widget>[ new Container( child: new Text(
articleTitle,//标题 style: new TextStyle( fontSize: 20.0, fontWeight:
FontWeight.w700), maxLines: 1, overflow: TextOverflow.ellipsis, ), alignment:
FractionalOffset.topLeft, ), new Container( child: new
Text("${data.articleBrief}",//概要 style: new TextStyle(fontSize: 16.0),
maxLines: 2, overflow: TextOverflow.ellipsis), alignment: Alignment.topLeft, ),
new Expanded( child: new Container( margin: new EdgeInsets.fromLTRB(0.0, 5.0,
0.0, 0.0), child: new Stack( children: <Widget>[ new Container( child: new
Text("${data.articleAuthor}", style: new TextStyle(fontSize: 10.0)),//作者
alignment: FractionalOffset.bottomLeft, ), new Container( child: new
Text(time_str, style: new TextStyle(fontSize: 10.0)),//时间 alignment:
FractionalOffset.bottomRight, ), ], ), ), ) ], ), ), flex: 3, ), ], ), new
Divider(), //分割线 ], ), ) /** * 列表中图片加载 */ getImage(String img_url) { return new
CachedNetworkImage( imageUrl: img_url, errorWidget: new Icon(Icons.error), fit:
BoxFit.cover, height: 85.0, width: 100.0, ); }
上述代码对应显示效果如下:

代码中CachedNetworkImage为网络图片缓存组件cached_network_image
<https://pub.dartlang.org/packages/cached_network_image>加载。

<>网络请求

网络请求使用的是开源的Dio <https://pub.dartlang.org/packages/dio>,也可以直接使用http发送请求,
Dio dio = new Dio(); Response response = await dio.get(url); var jsonString =
response.data;
<>json解析

json_serializable <https://pub.dartlang.org/packages/json_serializable>
这个可以对json做很好的解析,类似于安卓的Gson,具体使用可以参考这篇文章 <https://www.jianshu.com/p/4210536124b1>
,博主也是按文章进行操作的。
try { var news = new news_enity.fromJson(jsonString); var code = news.code; if
(code == 0) { Result result = news.result; datas = result.data; } } catch (e) {
print("异常==》" + e.toString()); }
<>数据显示

使用 setState,将请求获得的数据datas传递给ListView的数据源listData
setState(() { listData= datas; });
但列表显示肯定是要等到下网络请求到时间后才能显示的,所以有段时间我们需要用精度条转圈来显示等待,没有数据时,加载loading进度条,有数据后立马显示列表
getBody() { if (listData.isEmpty) { return getProgressDialog(); } else {
return new Container( padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: getListView(), ); } } getProgressDialog() { // //
CircularProgressIndicator是一个圆形的Loading进度条 return new Center(child: new
CircularProgressIndicator()); }
最后效果如下图


项目源代码地址 <https://github.com/zhibuyu/mystocks>,此项目为持续开发项目,欢迎Star和Fork