Flutter使用ListView加载列表数据

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

本文数据采用爬虫爬取华尔街见闻全球资讯,而后采用GraphQL接口请求数据。显示效果以下
在这里插入图片描述github

实现

  • 建立ListView 及每一个显示的item
  • 网络请求
  • json解析
  • 数据显示

建立ListView及每一个显示的item

使用以下代码建立一个ListView
其中listData 为列表加载的数据,因先初始化下 List listData = [];web

ListView getListView() => new ListView.builder(
      itemCount: (listData== null) ? 0 : listData.length,
      itemBuilder: (BuildContext context, int position) {
        return getItem(position);
      });

上面的getItem方法即为列表item的布局,使用Column与Row实现垂直和水平布局,核心代码以下:json

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加载。缓存

网络请求

网络请求使用的是开源的Dio,也能够直接使用http发送请求,网络

Dio dio = new Dio();
    Response response = await dio.get(url);
    var jsonString = response.data;

json解析

json_serializable这个能够对json作很好的解析,相似于安卓的Gson,具体使用能够参考这篇文章,博主也是按文章进行操做的。框架

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的数据源listDataide

setState(() {
      listData= datas;
    });

但列表显示确定是要等到下网络请求到时间后才能显示的,因此有段时间咱们须要用精度条转圈来显示等待,没有数据时,加载loading进度条,有数据后立马显示列表svg

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());
  }

最后效果以下图
在这里插入图片描述布局

项目源代码地址,此项目为持续开发项目,欢迎Star和Fork