You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Cloud Firestore有数据时我的StreamBuilder没有立即切换显示页面?

问题根因

你代码里的StreamBuilder存在两处核心错误:

  1. 数据存在的分支只构造了待办列表ListView,没有添加return关键字,该分支无有效返回组件,代码始终会走到末尾返回等级选择列表,自然不会完成切换。
  2. 仅判断snapshot.hasData不严谨:当用户首次进入,Firestore中对应文档还未创建时,snapshot返回的空DocumentSnapshot也会命中hasData == true的条件,会触发空数据异常。

修复方案

1. 先确认DatabaseService中getTodos方法的实现正确:

// DatabaseService类中需要正确返回对应用户文档的实时快照流
Stream<DocumentSnapshot> getTodos() {
  return userTodos.doc(userID).snapshots();
}

2. 修改StreamBuilder的逻辑,补充return和空判断:

StreamBuilder(
  stream: database.getTodos(),
  builder: (context, AsyncSnapshot snapshot) {
    // 先处理加载状态
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: CircularProgressIndicator());
    }
    // 处理错误状态
    if (snapshot.hasError) {
      return const Center(child: Text("加载数据失败"));
    }
    // 处理有数据的情况
    if (snapshot.hasData) {
      DocumentSnapshot doc = snapshot.data!;
      // 额外判断文档是否存在、数据是否不为空
      if (doc.exists) {
        Map<String, dynamic> level = doc.data() as Map<String, dynamic>;
        if (level.isNotEmpty) {
          // 这里必须加return,返回待办列表
          return ListView.separated(
            separatorBuilder: (BuildContext context, int index) {
              return const SizedBox(height: 10);
            },
            padding: const EdgeInsets.all(10),
            itemCount: level.length,
            itemBuilder: (buildContext, i) {
              String key = level.keys.elementAt(i);
              return ToDoItem(
                key,
                level[key]!,
                () => toggleDone(key),
              );
            });
        }
      }
    }
    // 所有不符合展示待办列表的情况,都返回等级选择页
    return ListView.separated(
      separatorBuilder: (BuildContext context, int index) {
        return const SizedBox(height: 10);
      },
      padding: const EdgeInsets.all(10),
      itemCount: levels.length,
      itemBuilder: (buildContext, i) {
        String key = levels.keys.elementAt(i);
        return LevelItem(
          key,
          levels[key]!,
          () => toggleDone(key),
          () => select(key),
        );
      });
  },
);

修改完成后,存入Firestore的数据触发快照更新时,StreamBuilder就会自动切换到待办列表展示。

内容的提问来源于stack exchange,提问作者Lars

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:06:06