简体   繁体   English

错误 state:使用 StreamBuilder 和 Firestore 时,快照在 flutter 中既没有数据也没有错误

[英]Bad state: Snapshot has neither data nor error in flutter when using StreamBuilder and Firestore

I'm adding data from Firestore to a Stream from StreamBuilder , but I'm getting the following error:我正在将 Firestore 中的数据添加到Stream中的StreamBuilder ,但出现以下错误:

Exception has occurred.发生异常。 StateError (Bad state: Snapshot has neither data nor error StateError (Bad state: Snapshot has neither data nor error

My code.我的代码。

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  AppState? estado;

  static String? userID = FirebaseAuth.instance.currentUser?.uid;
  static final userColeccion = FirebaseFirestore.instance.collection("users");

  var groupfav = ' ';
  Stream<QuerySnapshot>? taskGroup;

  @override
  void initState() {
    super.initState();
    getGroupFavData();
  }

  void getGroupFavData() async {
    var groupFavData = await userColeccion.doc("$userID").get();
    var groupfav = groupFavData.data()!['groupfav'];

    taskGroup = FirebaseFirestore.instance
        .collection("groups")
        .doc(groupfav) // pass the obtained value
        .collection("task")
        .snapshots();
  }

  @override
  Widget build(BuildContext context) {
    estado = Provider.of<AppState>(context, listen: true);
    return Scaffold(
      appBar: AppBar(
        title: const Text("Home"),
        automaticallyImplyLeading: false,
      ),
      body: StreamBuilder(
        stream: taskGroup,
        builder: (
          BuildContext context,
          AsyncSnapshot<QuerySnapshot> snapshot,
        ) {
          if (snapshot.hasError) {
            return const Text("error");
          }
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Text("Loading");
          }
          var data = snapshot.requireData;

          return ListView.builder(
            itemCount: data.size,
            itemBuilder: (context, index) {
              return Card(
                child: ListTile(
                  title: Text("${data.docs[index]['titulo']}"),
                  subtitle: Text("${data.docs[index]['contenido']}"),
                  onTap: () {},
                  trailing: IconButton(
                    icon: const Icon(Icons.delete),
                    color: Colors.red[200],
                    onPressed: () {},
                  ),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

Ok, looking at your issue, I see that 1) you need to get the data of the document BEFORE you start listening on that document, which is normal, so you want to do a call first to the collection, get the document, then listen on the document's collection called task , which makes sense.好的,看看你的问题,我明白了 1) 你需要在开始收听该文档之前获取文档的数据,这是正常的,所以你想先调用集合,获取文档,然后监听名为task的文档集合,这是有道理的。 Your issue is still an asynchronous issue.您的问题仍然是异步问题。 The app is rebuilding on a stream that still hasn't arrived;该应用程序正在重建 stream,但仍未到达; you have to fix the sequence of things.你必须确定事物的顺序。

You then need to switch things up a bit and do the following:然后你需要稍微改变一下并执行以下操作:

Option #1 : a) Use a FutureBuilder : this will allow you to make the async call to get the document name based on the user Id b) After you get the document associated to that user, you want to listen on the stream produced by the collection called tasks in that document.选项 #1 :a) 使用FutureBuilder :这将允许您根据用户 ID 进行异步调用以获取文档名称 b) 在您获得与该用户关联的文档后,您想要收听stream该文档中称为任务的集合。 There is where then you can hook up the StreamBuilder .在那里你可以连接StreamBuilder

Option #2 : a) Keep things the way you have, but do a listen on the taskGroup snapshots;选项 #2 :a) 保持原样,但听取taskGroup快照; but keep rebuilding the list as the values arrive on that collection.但随着值到达该集合,继续重建列表。

Those are my suggestions.这些是我的建议。

Here's some brief code on option 1:这是选项 1 的一些简短代码:


// .. in your Scaffold's body:

Scaffold(
 body: FutureBuilder( // the future builder fetches the initial data
   future: userColeccion.doc("$userID").get(),
   builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {

     if (snapshot.hasData) {
       var groupfav = snapshot.data()!['groupfav'];

       // then once the 'groupfav' has arrived, 
       // start listening on the taskGroup

       taskGroup = FirebaseFirestore.instance
        .collection("groups")
        .doc(groupfav) // pass the obtained value
        .collection("task")
        .snapshots();

       return StreamBuilder(
           stream: taskGroup,
           builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          // the rest of your code

       });
     }

     return CircularProgressIndicator();
   }
)

)

Option 2 would be something like:选项 2 类似于:

List<Task> userTasks = [];

void getGroupFavData() async {
    var groupFavData = await userColeccion.doc("$userID").get();
    var groupfav = groupFavData.data()!['groupfav'];

    taskGroup = FirebaseFirestore.instance
        .collection("groups")
        .doc(groupfav) // pass the obtained value
        .collection("task")
        .snapshots().listen((snapshot) {
          // here populate a list of your tasks
          // and trigger a widget rebuild once you've grabbed the values
          // and display it as a list on the UI

          setState(() {

            userTasks = snapshot.docs.map((d) => Task.fromJson(d.data())).toList();
          });
 
       });
  }

And in your Scaffold , you can have a ListView just rendering the items on that task list, like:在你的Scaffold中,你可以有一个ListView来呈现该任务列表中的项目,例如:

ListView.builder(
  itemCount: userTasks.length,
  itemBuilder: (context, index) {
     // render your tasks here
  })

Here's a Gist with some working code to illustrate my point.这是一个Gist和一些工作代码来说明我的观点。 Run it on DartPad and you'll see how using a FutureBuilder wrapping a StreamBuilder will accomplish what you want.在 DartPad 上运行它,您将看到如何使用包装 StreamBuilder 的 FutureBuilder 来完成您想要的。

If you run the above code on DartPad, you'll get the following output:如果你在 DartPad 上运行上面的代码,你将得到以下 output:

在此处输入图像描述

Hope those pointers take you somewhere.希望这些指针能带你到某个地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 StreamBuilder 未更新 Flutter 中的 Firestore 数据 - StreamBuilder not updating Firestore data in Flutter Flutter Streambuilder stream FirebaseFirestore 快照数据不一致 - Flutter Streambuilder stream inconsistent FirebaseFirestore snapshot data Flutter 云Firestore StreamBuilder<documentsnapshot> 错误</documentsnapshot> - Flutter cloud firestore StreamBuilder<DocumentSnapshot> error 使用 Flutter 和 Firestore 中的新数据更新 StreamBuilder - Updating a StreamBuilder with new data in Flutter and Firestore Flutter 流生成器在发布模式下没有数据 - Flutter streambuilder has no data in release mode 发生异常。 StateError(错误 state:DocumentSnapshotPlatform 中不存在字段)- 当我发出请求时 Flutter Firestore - Exception has occurred. StateError (Bad state: field does not exist within the DocumentSnapshotPlatform) - When I make a request Flutter Firestore 使用 StreamBuilder 从 Firestore 文档中获取数据 - Fetch data from Firestore Document using StreamBuilder 在 flutter 中使用 StreamBuilder 和 collectionrefrence 作为快照 - use StreamBuilder with collectionrefrence as snapshot in flutter Flutter:更新单个文档时,StreamBuilder 获取其他 Firestore 文档 - Flutter: StreamBuilder gets other firestore documents when updating a single document StreamBuilder 在不应该有数据的时候有数据 - StreamBuilder has data when it shouldn't
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM