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

Flutter StreamBuilder类型不匹配求助:DocumentSnapshot无法赋值给QuerySnapshot

问题:StreamBuilder类型不匹配导致DropdownMenu无法加载Firestore数据

错误信息

The argument type 'Stream<DocumentSnapshot<Map<String, dynamic>>' can't be assigned to the parameter type 'Stream<QuerySnapshot<Object?>>?'

用户代码

StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance
          .collection('reports')
          .doc(userID)
          .snapshots(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          const CircularProgressIndicator();
        } else {
          final currencyItems = <DropdownMenuItem>[];
          for (var i = 0; i < snapshot.data!.docs.length; i++) {
            final DocumentSnapshot snap = snapshot.data!.docs[i];
            currencyItems.add(
              DropdownMenuItem(
                value: snap.id,
                child: Text(
                  snap.id,
                  style: const TextStyle(color: Color(0xff11b719)),
                ),
              ),
            );
          }
          return Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Icon(Icons.abc, size: 25, color: Color(0xff11b719)),
              const SizedBox(width: 50.0),
              DropdownButton(
                items: currencyItems,
                onChanged: (currencyValue) {
                  setState(() {
                    final selectedCurrency = currencyValue;
                  });
                },
                // value: selectedCurrency,
                isExpanded: false,
                hint: new Text(
                  "Choose Currency Type",
                  style: TextStyle(color: Color(0xff11b719)),
                ),
              ),
            ],
          );
        }
        return Container();
      },
    ),

Firebase Firestore结构

Firebase Firestore结构


解决建议

错误原因

你调用了.doc(userID).snapshots(),这返回的是单个文档的流(Stream<DocumentSnapshot>),但你的StreamBuilder声明为接收集合查询快照的流(Stream<QuerySnapshot>),两者类型不匹配,导致报错。结合你的Firestore结构,reports集合下的用户文档直接存储了EUR、USD等货币字段,需要调整代码逻辑处理单个文档的数据。

修改后的代码

// 需在State类中声明成员变量
String? selectedCurrency;

StreamBuilder<DocumentSnapshot>(
  stream: FirebaseFirestore.instance
      .collection('reports')
      .doc(userID)
      .snapshots(),
  builder: (context, snapshot) {
    // 处理数据未加载或为空的情况
    if (!snapshot.hasData || snapshot.data!.data() == null) {
      return const CircularProgressIndicator();
    }

    // 获取文档中的所有货币字段
    final Map<String, dynamic> reportData = snapshot.data!.data() as Map<String, dynamic>;
    // 遍历字段名生成Dropdown选项
    final currencyItems = reportData.keys.map((currency) {
      return DropdownMenuItem(
        value: currency,
        child: Text(
          currency,
          style: const TextStyle(color: Color(0xff11b719)),
        ),
      );
    }).toList();

    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        const Icon(Icons.abc, size: 25, color: Color(0xff11b719)),
        const SizedBox(width: 50.0),
        DropdownButton(
          items: currencyItems,
          onChanged: (currencyValue) {
            setState(() {
              // 修改类成员变量,确保UI更新
              selectedCurrency = currencyValue;
            });
          },
          value: selectedCurrency,
          isExpanded: false,
          hint: const Text(
            "Choose Currency Type",
            style: TextStyle(color: Color(0xff11b719)),
          ),
        ),
      ],
    );
  },
)

关键调整点

  1. 将StreamBuilder的类型从QuerySnapshot改为DocumentSnapshot,匹配数据源的类型。
  2. 不再遍历snapshot.data!.docs(单个文档无该列表),而是直接获取文档数据的keys作为货币选项。
  3. 将selectedCurrency改为State类的成员变量,确保setState能正确触发UI更新。

内容的提问来源于stack exchange,提问作者Jarosław Gawlik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:51:48