【问题标题】:Null List after data retrieval from Firestore in Flutter从 Flutter 中的 Firestore 检索数据后的空列表
【发布时间】:2020-12-10 01:17:16
【问题描述】:

我是 Flutter 的新手,如果这个问题看起来微不足道或无关紧要,我很抱歉!

我创建了另一个用于获取和设置数据的类Repository,因为我使用 Cloud Firestore,我想要针对这个特定问题的数据存储在一个集合中,所以我将集合中的所有文档都作为 @ 987654323@,然后将所有文档添加到List<DocumentSnapshot>

方法如下:

Future<List<DocumentSnapshot>> getCollection(CollectionReference colRef) async {
    List<DocumentSnapshot> dummyList = new List();
    await colRef.getDocuments().then((value) {
      dummyList.addAll(value.documents);
    });
    return dummyList;
  }

存储库:

CollectionReference memoriesColRef =
    _firestore
        .collection("username")
        .document("memories")
        .collection("allMem");

    List<DocumentSnapshot> documentList = new List();
    await getCollection(memoriesColRef).then((value) {
      documentList.addAll(value);
    });

毕竟,我在我的 UI 类中设置了一个方法,调用它 Repository,当我在 build 函数中调用它时,它可以完美运行,我已经传递给访问的全局列表数据,无法在其中添加值

UI 类

build(...) {
  getMemories().then((value) {
      print("value size: " + value.length.toString()); // 1
      memoriesListMap.addAll(value); // global variable
    });
  print("valSize: " + memoriesListMap.length.toString()); // 0
  print("val: " + memoriesListMap[0]["title"]); // error line
}

Future<List<Map<String, dynamic>>> getMemories() async{
    List<Map<String, dynamic>> dummyListMap = new List();

    await MemoryOper().getMemories().then((value) {
      print("memVal: " + value[0]["title"]); // appropriate value
      dummyListMap.addAll(value);
    });
    return dummyListMap;
  }

错误 RangeError (index): Invalid value: Valid value range is empty: 0\

我不知道是什么原因造成的,但请帮帮我!谢谢

编辑:

ListView.builder(
                itemBuilder: (BuildContext context, int index) {
                  String title = memoriesListMap[index]["title"]; // error prone line
                  int remind = memoriesListMap[index]["remind"];
                  String link = memoriesListMap[index]["link"];

【问题讨论】:

  • 这能回答你的问题吗? What is a Future and how do I use it?
  • 注意“我如何使用它”部分。如果你想构建依赖于 Future 结果的东西,你需要FutureBuilder
  • 作为个人附注,尽量不要混用.then()await。对于 Futures 和 async/await 的新手来说,这可能会非常令人困惑。一旦您了解它们的方式,将两者一起使用并没有错,但对于初学者来说,如果您选择其中一个会更容易。我建议await,这样更难犯这样的错误。
  • 理想情况下,如果我遵循这个答案,我应该能够形成一个解决方案,对吧?
  • 是的,确实如此。无论是假设的披萨外卖还是从 Firestore 加载东西,“我稍后获取数据,我该怎么办?”的概念。总是一样的。

标签: flutter asynchronous dart google-cloud-firestore future


【解决方案1】:

除了 nvoigt 所说的之外,article 将帮助您了解如何实现 Future Builder,在您的具体情况下,您可以执行以下操作:

build(...){
..
body: getMemories(),
..
}

Widget getMemories() {
  return FutureBuilder(
    builder: (context, projectSnap) {
      if (projectSnap.connectionState == ConnectionState.none &&
          projectSnap.hasData == null) {
        return Container();
      }
      return ListView.builder(
        itemCount: projectSnap.data.length,
        itemBuilder: (context, index) {
          ProjectModel project = projectSnap.data[index];
          return Column(
            children: <Widget>[
              // Widget to display the list of project
            ],
          );
        },
      );
    },
    future: getCollection(), //this is the important part where you get the data from your Future
  );
}

【讨论】:

  • 是的,FutureBuilder 有效!我在和 nvoigt 的谈话中提到过。
【解决方案2】:

我认为您在添加元素之前正在访问它,因为它是 async 方法。
尝试这样的事情,

build(...) {
  getMemories().then((value) {
      print("value size: " + value.length.toString()); // 1
      memoriesListMap.addAll(value); // global variable
      print("valSize: " + memoriesListMap.length.toString()); // 0
      print("val: " + memoriesListMap[0]["title"]); 
   });
}

希望它有效!

【讨论】:

  • 是的,这可行,但我必须在 .then() 之外使用该变量,如果需要,我可以将代码发布在我使用它的地方
  • 是的,请张贴。如果你必须使用它,那么你可以等到async函数被执行。
  • 这行不通。如果您需要构建结果,则需要等待结果,而不是使用.then()。由于构建方法不能是异步的,所以你不能。所以你需要另一种方式。这通常使用 FutureBuilder 来处理,请参阅我的重复投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 2021-04-17
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多