dart 带有嵌套ListView的Flutter ListView对屏幕外小部件抛出RangeError

rqmkfv5c  于 2023-02-20  发布在  Flutter
关注(0)|答案(1)|浏览(171)

第一次在Flutter工作,不是一个真正的软件向导。我已经建立了一个应用程序,连接到Firebase和检索数据结构作为一个Map(所有登录后)。这工作正常。但是,数据是(种)列表的列表(或Map的Map)等。基本结构是:

{
title1: {
      item-A: {
               0: line1,
               1: line2,
               2: line3,
              },
      item-B: {
               0: line1,
               1: line2,
               2: line3,
              }
        },
title2: {
      item-A: {
               0: line1,
...
}

架构可以有更多或更少的标题、项目和行,但结构是相同的。
我实现的代码通过FutureBuilder从数据库(Firebase Realtime Database)获取值,格式化结果并显示它们。检索结果和一般显示格式按预期工作,但在显示一个巨大的红色框之前,我只能看到一个或两个列表小部件,并得到以下错误:

The following IndexError was thrown building:
RangeError (index): Index out of range: index should be less than 1: 1

如果我运行热刷新或热重新加载,或者只是重新加载浏览器,我会得到更多行的Widget,错误会更改为下一个索引增量:

The following IndexError was thrown building:
RangeError (index): Index out of range: index should be less than 4: 5

如果我不断刷新,最终整个列表都会显示出来,错误也会消失。然而,显然这不是我想要的行为。我一直在研究这个问题,并测试了不同的方法,但我真的不明白问题出在哪里。
我的代码(省略了一些细节)如下所示:

Widget build(BuildContext context) {
    return Consumer<ApplicationState>(
        builder: (context, appState, child) {
          selectedIndex.add(-1);

          return Scaffold(
              ...
              body: FutureBuilder(
                future: futureDataRetreiverFunction(),
                builder: (BuildContext context, AsyncSnapshot<Map> snapshot) {

                if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
                  ... // convert the snapshot.data here // 
                  return Container(
                      ...
                      child: ListView(
                          shrinkWrap: true,
                          children: [
                            Form(
                            key: _formKey,
                            child: Column(
                                children: [
                                  ListView.builder(
                                    scrollDirection: Axis.vertical,
                                    controller: ScrollController(),
                                    shrinkWrap: true,
                                    itemCount: snapshotData.keys.length, // the data is a Map
                                    itemBuilder: (BuildContext context, int index) =>
                                      Column(
                                          children: [
                                            ...
                                            Row(
                                              children: [
                                                Text(snapshotData.keys.elementAt(index)),
                                              ]
                                            ),
                                            Row(
                                              children: [
                                                Text(selectedIndex[index].toString())
                                              ]
                                            ),
                                            Row(
                                              children: [
                                              Flexible(
                                                fit: FlexFit.loose,
                                                child: Padding(
                                                  padding: const EdgeInsets.fromLTRB(5, 0, 0, 10),
                                                    child: ListView.builder(
                                                      shrinkWrap: true,
                                                      primary: false,
                                                      itemCount: snapshotData.values.elementAt(index)[1].length,
                                                      itemBuilder: (BuildContext context, int index2) =>
                                                        Text(snaptshotData.values.elementAt(index)[1][index2])
                                                    )
                                                  )
                                                )]
                                              )
                                            ])
                                           )
                                         ])
                                        ])
                                       );
...
46scxncf

46scxncf1#

Vishal在他对这个问题的第一个评论中指出了答案。我使用“selectedIndex”作为setState({})调用的一部分,以更改onTap: () {}调用的一些视觉效果。(List selectedIndex = [];),但在构建器中只向索引添加了1项。然而,在本例中,总共构建了6项(在其他情况下更多/更少),这就抛出了索引错误,这就是为什么它会在重新加载时递增(调用了另一个seletedIndex.add(-1);)。我插入了一个快速函数,根据快照数据的大小预先填充索引,沿着所示:

for (var counter=0; counter<snapshotData.keys.length; counter++) {
    selectedIndex.add(-1);
}

这解决了索引RangeError。

相关问题