【问题标题】:How to build a dynamic list in Flutter?如何在 Flutter 中构建动态列表?
【发布时间】:2018-05-29 08:02:45
【问题描述】:

我将此小部件附加到 Scaffold 正文。小部件获得一个返回 json 对象的 async 方法。

我想从该 json 对象动态构建一个列表。问题是屏幕是空的。由于某种原因,当列表准备好或类似的东西时,这个小部件需要刷新自己。

有什么想法吗?

class TestList extends StatelessWidget {
  final quiz;

  TestList({this.quiz});

  @override
  Widget build(BuildContext context) {
    var listArray = [];

    this.quiz.then((List value) {   // this is a json object

      // loop through the json object
      for (var i = 0; i < value.length; i++) {

        // add the ListTile to an array
        listArray.add(new ListTile(title: new Text(value[i].name));

      }
    });

    return new Container(
        child: new ListView(
      children: listArray     // add the list here.
    ));
  }
}

【问题讨论】:

    标签: listview asynchronous flutter


    【解决方案1】:

    您可以使用setState 重新构建用户界面。

    例子:

    class TestList extends StatefulWidget {
    
      final Future<List> quiz;
    
      TestList({this.quiz});
    
      @override
      _TestListState createState() => new _TestListState();
    
    }
    
    class _TestListState extends State<TestList> {
    
      bool loading = true;
    
      _TestListState(){
        widget.quiz.then((List value) {
    
          // loop through the json object
          for (var i = 0; i < value.length; i++) {
    
            // add the ListTile to an array
            listArray.add(new ListTile(title: new Text(value[i].name));
    
            }
    
                //use setState to refresh UI
                setState((){
              loading = false;
            });
    
        });
      }
    
      @override
      Widget build(BuildContext context) {
    
        List<Widget> listArray = [];
    
        return new Container(
            child: new ListView(
                children: loading?[]:listArray     // when the state of loading changes from true to false, it'll force this widget to reload
            ));
    
      }
    
    }
    

    【讨论】:

    • setState() isn't defined for the class TestList
    • 将您的 TestList 设为 StatefulWidget。等一下,我将编辑我的答案以实现 StatefulWidget。
    • 我认为setState((){ loading = false; }); 可能需要设置在循环之外
    • 是的,虽然有些奇怪。如果我注释掉setState()loadingwidget.quiz.then.. 中是错误的,除非我将bool loading = true; 移到它上面。
    • setState(() { loading = false; }); 内的 widget.quiz.then.. 出于某种原因进行了无限循环。也许一些范围问题..
    【解决方案2】:

    您可以使用 FutureBuilder 来帮助处理小部件状态:

    new FutureBuilder<List>(
      future: widget.quiz,
      builder:
          (BuildContext context, AsyncSnapshot<List> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
            return new Text('Waiting to start');
          case ConnectionState.waiting:
            return new Text('Loading...');
          default:
            if (snapshot.hasError) {
              return new Text('Error: ${snapshot.error}');
            } else {
              return new ListView.builder(
                  itemBuilder: (context, index) =>
                      new Text(snapshot.data[index].name),
                  itemCount: snapshot.data.length);
            }
        }
      },
    )
    

    基本上,它会根据未来状态通知 builder 上指定的方法。一旦 future 收到一个值并且没有错误,您可以使用 ListView.builder 来制作列表,这是在所有项目都属于同一类型时创建列表的便捷方法。

    更多信息https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html

    【讨论】:

    • 虽然你的回答更符合 Async 标准,但我不知道为什么我收到了多次调用和 snapshot.hasError 被执行,ListBuilder 从未被执行
    猜你喜欢
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    相关资源
    最近更新 更多