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

Flutter FutureBuilder报错:_JsonQuerySnapshot无data方法求解

错误分析与解决方案

核心报错原因

报错NoSuchMethodError: Class '_JsonQuerySnapshot' has no instance method 'data'的直接原因是:

  • 在getOutletById方法中,错误请求了店铺下的products集合(返回QuerySnapshot对象),却试图调用只有DocumentSnapshot才有的data()方法。QuerySnapshot用于表示集合查询结果,没有data()方法,因此触发错误。
  • 逻辑偏差:该方法目的是获取店铺详情,但实际请求的是店铺下的商品集合,完全偏离需求。

分步解决方案

1. 修复getOutletById方法(获取店铺详情)

修改方法逻辑,直接请求店铺文档本身,而非商品集合:

Future<Map<String, dynamic>> getOutletById(String outId) async {
  final Map<String, dynamic> idOutlet = {};
  _outletMerchant.clear();
  try {
    // 直接获取店铺文档,而非products子集合
    final outletDoc = await outletsCollectionRef.doc(outId).get();
    if (!outletDoc.exists) {
      print("店铺文档不存在");
      return idOutlet;
    }
    // DocumentSnapshot拥有data()方法,可获取店铺数据
    final outletResponse = outletDoc.data()!;

    final outletMerchantData = await firestore
        .collection(allUserCollection)
        .doc(outletResponse[merchantId])
        .get();

    final merchantResponse = outletMerchantData.data();
    print('outlet merchant data-->>>> ${merchantResponse}');
    if (merchantResponse != null) {
      _outletMerchant.addAll(merchantResponse);
    }

    idOutlet.addAll(outletResponse);

  } catch (err) {
    print(err);
  }
  return idOutlet;
}

2. 修复商品列表的StreamBuilder逻辑

原getProductsAndImages方法错误将QuerySnapshot当作单个文档处理,同时ListView.builder缺少itemCount会导致无限循环:

第一步:修改getProductsAndImages方法

改为接收单个商品文档,直接处理数据:

Widget getProductsAndImages(BuildContext context, QueryDocumentSnapshot productDoc) {
  final productData = productDoc.data() as Map<String, dynamic>;
  final outletId = ModalRoute.of(context)!.settings.arguments as String;
  
  // 处理图片列表,避免空值和索引越界
  List<String> productImgs = List.from(productData['productImageURL'] ?? []);
  String? imageUrl = productImgs.length > 4 ? productImgs[4] : null;

  return ProductItem(
    productId: productDoc.id, // 商品ID为文档ID
    productName: productData['productName'] ?? '无名商品',
    productDescription: productData['prodDesc'] ?? '',
    productPrice: double.tryParse(productData['productPrice'].toString()) ?? 0.0,
    images: imageUrl,
    category: productData['category'] ?? '',
    count: double.tryParse(productData['countInStock'].toString()) ?? 0.0,
    outletId: outletId
  );
}

第二步:替换原ListView.builder为带StreamBuilder的列表

在FutureBuilder的Column中,将原ListView.builder替换为:

StreamBuilder<QuerySnapshot>(
  stream: productsRef.doc(outletId).collection('products').snapshots(),
  builder: (ctx, productSnapshot) {
    if (!productSnapshot.hasData) {
      return const Center(child: Text('加载商品中...'));
    }
    final products = productSnapshot.data!.docs;
    return ListView.builder(
      padding: EdgeInsets.zero,
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemCount: products.length, // 必须设置itemCount,避免无限循环
      itemBuilder: (ctx, index) {
        return getProductsAndImages(context, products[index]);
      },
    );
  },
)

3. 完善FutureBuilder的空值处理

原代码中判断snapshot.data.length == 0不合理(返回的是Map,应使用isEmpty),同时添加空值默认值避免崩溃:

builder: (ctx, AsyncSnapshot<Map<String, dynamic>> snapshot) {
  if (snapshot.connectionState == ConnectionState.waiting || snapshot.data == null) {
    return const Center(child: Text("加载中..."));
  }
  final outletData = snapshot.data!;
  if (outletData.isEmpty) {
    return const Center(child: Text("未找到店铺信息"));
  }
  return SingleChildScrollView(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        ShopHeader(
          outletName: outletData['outletName'] ?? '无名店铺',
          outletImage: outletData['outletImageURL'] ?? '',
          location: outletData['location'] ?? '',
          description: outletData['description'] ?? '',
          phoneNum: outletData['phone'] ?? '',
          merchantId: outletData['merchantId'] ?? '',
          outletId: outletId,
        ),
        // 其余代码保持不变
      ],
    ),
  );
},

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 21:54:16