Flutter使用ListView加载列表数据

Posted 子不语归来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter使用ListView加载列表数据相关的知识,希望对你有一定的参考价值。

移动端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加载。

网络请求

网络请求使用的是开源的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的数据源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());
  

最后效果如下图

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

以上是关于Flutter使用ListView加载列表数据的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 专题15 图解 ListView 异步加载数据与等待 #yyds干货盘点#

Flutter ListView 未更新

Flutter 之列表和头部 (ListView + Header)

当我更新 ListView 上的列表时,Flutter 页面不会重新加载

Flutter 专题16 图解 ListView下拉刷新与上拉加载 #yyds干货盘点#

Flutter 专题17 图解 ListView下拉刷新与上拉加载 #yyds干货盘点#