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

Flutter使用Firebase查询结合Model类时map内print不执行问题

Flutter Firestore查询Stream回调不执行问题

问题背景

在Flutter项目中对接Firebase Firestore实现数据查询时,做了如下前置操作:

  • 定义业务数据类ProductModel
  • 在Firestore的ProductModel集合下新增2条测试文档数据
  • 编写按钮点击触发的getMessagesTestTest()方法实现数据查询逻辑

问题现象

点击按钮触发查询函数执行后,snapshots().map()回调循环内的print("start in loop");、print('doc.id == ${doc.id}');两条打印语句始终没有输出,notesFromFirestore列表一直为空,判断为代码逻辑实现错误导致。

问题相关代码

初始查询函数实现

void getMessagesTestTest() async{

    final aa = await _firestore.collection('ProductModel').snapshots().map((notes){
      notesFromFirestore.clear();
      for(final DocumentSnapshot<Map<String,dynamic>> doc in notes.docs){
        print("start in loop");
        print('doc.id == ${doc.id}');
        notesFromFirestore.add(ProductModel.fromDocumentSnapshot(doc:doc));
      }
      return notesFromFirestore;});
    print( 'List Size = ${notesFromFirestore.length}');
    var count = 0;
    for (final ProductModel notesFromFirestoreA in notesFromFirestore) {
      count++;
      print('Loop Counter == ${count}');
      print('Id == ${notesFromFirestoreA.id}');
      print('Name == ${notesFromFirestoreA.name}');
      print('Price == ${notesFromFirestoreA.price}');
      print('Brand == ${notesFromFirestoreA.brand}');
      print('image == ${notesFromFirestoreA.image}');
    }
  }

按钮点击触发逻辑

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Record'),
        leading: null,
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.add),
            onPressed: (){
              Navigator.pushNamed(context, creationCategory.id);
            },
          ),
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () async {
              getMessagesTestTest();
            },
          ),
        ],
      ),
      body: SafeArea(
        child: Container(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Text('Trahs Collection',
              style: const TextStyle(
                color: Colors.black38, fontWeight: FontWeight.bold, fontSize: 40),
              ),
              ItemStream(),
            ],
          ),
          ),
      ),
      );
  }

ProductModel数据类定义

class ProductModel {
  static const ID = "id";
  static const IMAGE = "image";
  static const NAME = "name";
  static const BRAND = "brand";
  static const PRICE = "price";

  String? id;
  String? image;
  String? name;
  String? brand;
  int? price;

  ProductModel(
      {required this.id,
        required this.image,
        required this.name,
        required this.brand,
        required this.price});

  factory ProductModel.fromFire(QueryDocumentSnapshot snapshot) {
    return ProductModel.fromMap(snapshot as Map<String, dynamic>);
  }
  factory ProductModel.fromDocumentSnapshot({required DocumentSnapshot<Map<String,dynamic>> doc}){
    return ProductModel(
      id: doc.data()!["id"],
      image: doc.data()!["image"],
      name: doc.data()!["name"],
      brand: doc.data()!["brand"],
      price: doc.data()!["price"],
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'image': image,
    'name': name,
    'brand': brand,
    'price': price,
  };

  ProductModel.fromMap(Map<String, dynamic> data) {
    id = data[ID];
    image = data[IMAGE];
    name = data[NAME];
    brand = data[BRAND];
    price = data[PRICE];
  }
}

问题根因与修复

根因说明

snapshots()方法返回值为Stream类型,Dart中的Stream是懒执行对象:仅对Stream做map转换操作但不调用listen()注册监听的话,Stream不会实际启动数据拉取流程,因此map回调内的逻辑永远不会触发。

修复后代码

2022-06-21调整代码,将函数返回值改为Future<void>,为map转换后的Stream添加listen监听后功能正常,代码如下:

Future<void> getMessagesTestTest() async{

    var aa = await _firestore.collection('ProductModel').snapshots().map((notes){
      notesFromFirestore.clear();
      for(final DocumentSnapshot<Map<String,dynamic>> doc in notes.docs){
        log("start in loop");
        log('doc.id == ${doc.id}');
        notesFromFirestore.add(ProductModel.fromDocumentSnapshot(doc:doc));
      }
      return notesFromFirestore;});
    aa.listen(
          (event) => print("Data Retrieved"),
    );
    print( 'List Size = ${notesFromFirestore.length}');
    var count = 0;
    for (final ProductModel notesFromFirestoreA in notesFromFirestore) {
      count++;
      print('Loop Counter == ${count}');
      print('Id == ${notesFromFirestoreA.id}');
      print('Name == ${notesFromFirestoreA.name}');
      print('Price == ${notesFromFirestoreA.price}');
      print('Brand == ${notesFromFirestoreA.brand}');
      print('image == ${notesFromFirestoreA.image}');
    }
  }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:30:45