繁体   English   中英

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

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

我正在将 Firestore 中的数据添加到Stream中的StreamBuilder ,但出现以下错误:

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

我的代码。

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: () {},
                  ),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

好的,看看你的问题,我明白了 1) 你需要在开始收听该文档之前获取文档的数据,这是正常的,所以你想先调用集合,获取文档,然后监听名为task的文档集合,这是有道理的。 您的问题仍然是异步问题。 该应用程序正在重建 stream,但仍未到达; 你必须确定事物的顺序。

然后你需要稍微改变一下并执行以下操作:

选项 #1 :a) 使用FutureBuilder :这将允许您根据用户 ID 进行异步调用以获取文档名称 b) 在您获得与该用户关联的文档后,您想要收听stream该文档中称为任务的集合。 在那里你可以连接StreamBuilder

选项 #2 :a) 保持原样,但听取taskGroup快照; 但随着值到达该集合,继续重建列表。

这些是我的建议。

这是选项 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();
   }
)

)

选项 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();
          });
 
       });
  }

在你的Scaffold中,你可以有一个ListView来呈现该任务列表中的项目,例如:

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

这是一个Gist和一些工作代码来说明我的观点。 在 DartPad 上运行它,您将看到如何使用包装 StreamBuilder 的 FutureBuilder 来完成您想要的。

如果你在 DartPad 上运行上面的代码,你将得到以下 output:

在此处输入图像描述

希望这些指针能带你到某个地方。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM