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

如何在Flutter与Dart中从Firebase动态获取对应商店的子集合数据?

问题:点击商店按钮无法获取对应商店的商品

每个商店在Firebase的子集合中都有商品,点击商店按钮(ElevatedButton)时,无论点击哪个商店,始终只能获取到同一个商店的数据。

Firestore数据结构1
Firestore数据结构2
Firestore数据结构3

现有代码

Stores页面代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:user/screens/pages/pages/grid_fire.dart';

class Stores extends StatefulWidget {
  const Stores({super.key});

  @override
  State<Stores> createState() => _StoresState();
}

class _StoresState extends State<Stores> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: const Color.fromARGB(255, 27, 207, 186),
        title: const Text("Stores Near By"),
        actions: [
          IconButton(
            onPressed: () {
              Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => const Stores(),
                      ),
                  );
            },
            icon: const Icon(Icons.exit_to_app),
          ),
        ],
      ),
       body: StreamBuilder(
        stream: FirebaseFirestore
        .instance
        .collection("Stores")
        .snapshots(),
        builder: (BuildContext context,
                        AsyncSnapshot<QuerySnapshot> snapshot) {
                      if (!snapshot.hasData) {
                        return const Center(
                          child: CircularProgressIndicator(),
                        );
                      }
                      return GridView.count(
                        shrinkWrap: true,
                        physics: const ClampingScrollPhysics(),
                        crossAxisCount: 1,
                        mainAxisSpacing: 3,
                        childAspectRatio: 3,
                        crossAxisSpacing: 1,
                        children: snapshot.data!.docs.map((document) {
                          return InkWell(
                            child: SizedBox(
                              height:200,
                               width:double.infinity,
                              child: ElevatedButton(
                                    style: ElevatedButton.styleFrom(
                                    shadowColor: Colors.red,
                                    backgroundColor: const Color.fromARGB(255, 94, 8, 2),
                                    fixedSize: const Size(120, 34), // specify width, height
                                    shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(
                                            20,
                                          )),
                                  padding: const EdgeInsets.all(20), //content padding inside button

                                    ),
                                    onPressed: () => Navigator.pushReplacement(
                                      context, 
                                      MaterialPageRoute(
                                        builder: (context) =>  const GridFire()
                                        )
                                        ),
                                     child:
                                    Text(
                                          document["sname"],
                                          style: const TextStyle(
                                            fontSize: 30,
                                            fontWeight: FontWeight.w300,
                                          ),
                                        ),
                                      ),
                            ),
                          );
                          }).toList(),
                      );
                    },
        ),
    );
  }
}

GridFire页面代码

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:user/screens/pages/pages/stores.dart';


class GridFire extends StatefulWidget {
  const GridFire({super.key});

  @override
  State<GridFire> createState() => _GridFireState();
}

class _GridFireState extends State<GridFire> {
  @override
  Widget build(BuildContext context) {
   
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.green,
        title: const Text("Grid View1"),
      actions: [
          IconButton(
            onPressed: () {
              Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) =>  const Stores(),
                      ),
                  );
            },
            icon: const Icon(Icons.exit_to_app),
          ),
        ],
      ),

      body: StreamBuilder(
        stream: FirebaseFirestore
                .instance
                .collection("Stores")
                .doc("shop1-phone-number")
                .collection("items")
                .snapshots(),
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
                      if (!snapshot.hasData) {
                        return const Center(
                          child: CircularProgressIndicator(),
                        );
        }
                      return GridView.count(
                        shrinkWrap: true,
                        physics: const ClampingScrollPhysics(),
                        crossAxisCount: 1,
                        mainAxisSpacing: 5,
                        childAspectRatio: 5,
                        crossAxisSpacing: 10,
                        children: snapshot.data!.docs.map((document) {
                        return GestureDetector(
                            child: SizedBox(
              width: MediaQuery.of(context).size.width / 1.2,
              height: MediaQuery.of(context).size.height / 6,
              child: Text(
                // ignore: prefer_interpolation_to_compose_strings
              document['itemName'],
                style: const TextStyle(
                  fontSize: 25
                ),),
            ),
                          );
                        }).toList(),
                      );
                    },
        ),
    );
  }
}

解决方案

问题核心:GridFire页面硬编码了固定的商店文档ID,且跳转时未传递当前点击商店的ID。

步骤1:修改GridFire组件,支持接收商店ID

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:user/screens/pages/pages/stores.dart';

class GridFire extends StatefulWidget {
  // 新增参数:接收商店文档ID
  final String storeId;
  const GridFire({super.key, required this.storeId});

  @override
  State<GridFire> createState() => _GridFireState();
}

class _GridFireState extends State<GridFire> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.green,
        title: const Text("Grid View1"),
        actions: [
          IconButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const Stores(),
                ),
              );
            },
            icon: const Icon(Icons.exit_to_app),
          ),
        ],
      ),
      body: StreamBuilder(
        // 使用传递的storeId替代硬编码值
        stream: FirebaseFirestore
            .instance
            .collection("Stores")
            .doc(widget.storeId)
            .collection("items")
            .snapshots(),
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          if (!snapshot.hasData) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
          return GridView.count(
            shrinkWrap: true,
            physics: const ClampingScrollPhysics(),
            crossAxisCount: 1,
            mainAxisSpacing: 5,
            childAspectRatio: 5,
            crossAxisSpacing: 10,
            children: snapshot.data!.docs.map((document) {
              return GestureDetector(
                child: SizedBox(
                  width: MediaQuery.of(context).size.width / 1.2,
                  height: MediaQuery.of(context).size.height / 6,
                  child: Text(
                    document['itemName'],
                    style: const TextStyle(fontSize: 25),
                  ),
                ),
              );
            }).toList(),
          );
        },
      ),
    );
  }
}

步骤2:修改Stores页面跳转逻辑,传递商店ID

在ElevatedButton的点击事件中,传入当前商店的文档ID:

// 替换原跳转代码
onPressed: () => Navigator.pushReplacement(
  context, 
  MaterialPageRoute(
    builder: (context) => GridFire(storeId: document.id)
  )
),

修改完成后,点击不同商店按钮时,会将对应商店的ID传递给GridFire,从而加载该商店的专属商品数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:25:02