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

Flutter点击FloatingActionButton时从Firestore更新本地Map数据

Flutter点击按钮拉取Firestore Map数据更新本地对象实现方案

你当前的Firestore数据库结构如下:
Firestore数据库结构截图
要实现点击浮动按钮拉取数据更新本地Map的需求,按以下方式修改代码即可,同时修正了你现有代码里Firebase初始化、状态管理的两个隐性问题。


前置问题修正

你现有代码存在两个会导致功能异常的问题:

  • main函数中没有等待Firebase初始化完成就启动应用,后续调用Firestore接口会抛出未初始化错误
  • 顶层定义的Brain是全局变量,直接修改不会触发Flutter页面重绘,需要将其放到页面State中作为状态变量管理

核心实现逻辑

  1. 修正main函数初始化逻辑,确保Firebase初始化完成后再启动App
  2. 编写异步拉取方法:Firestore存储的Map键默认是字符串类型,和你本地用int作为键的结构不匹配,拉取后需要手动做类型转换
  3. 将拉取方法绑定到浮动按钮的点击事件,拉取成功后调用setState更新状态、刷新页面
  4. 代码中集合名、文档ID、字段名已经对应你截图里的配置,直接复制即可运行,如果后续改了路径自行替换即可

完整可运行代码

主逻辑代码(main.dart)

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

// 本地Brain默认初始值
Map<int, Map<int, String>> initialBrain = {
  0: {
    0: '0-0',
    1: '0-1',
    2: '0-2',
    3: '0-3',
    4: '0-4',
  },
  1: {
    0: '1-0',
    1: '1-1',
    2: '1-2',
    3: '1-3',
    4: '1-4',
  },
};

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 等待Firebase初始化完成再启动应用
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 将Brain作为页面状态变量管理
  late Map<int, Map<int, String>> brain;
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  @override
  void initState() {
    super.initState();
    // 页面初始化时加载默认值
    brain = Map.from(initialBrain);
  }

  // 拉取Firestore数据并更新本地Map的方法
  Future<void> fetchAndUpdateBrain() async {
    try {
      // 对应你截图里的集合、文档路径
      DocumentSnapshot doc = await _firestore
          .collection('Brain')
          .doc('pGQraR6uS0b03V2a3eqs')
          .get();

      if (!doc.exists) return;
      
      // 读取test字段存储的Map,Firestore返回的Map键默认是String类型
      Map<String, dynamic> rawData = Map<String, dynamic>.from(doc.get('test') as Map);
      Map<int, Map<int, String>> convertedData = {};

      // 遍历做类型转换,适配本地int键的结构
      rawData.forEach((outerKey, outerVal) {
        int outerKeyInt = int.parse(outerKey);
        Map<String, dynamic> rawInnerMap = Map<String, dynamic>.from(outerVal as Map);
        Map<int, String> convertedInnerMap = {};

        rawInnerMap.forEach((innerKey, innerVal) {
          convertedInnerMap[int.parse(innerKey)] = innerVal.toString();
        });

        convertedData[outerKeyInt] = convertedInnerMap;
      });

      // 更新状态触发页面刷新
      setState(() {
        brain = convertedData;
      });

    } catch (e) {
      debugPrint('数据拉取异常: $e');
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('数据拉取失败,请检查网络和权限配置'))
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Text(brain.toString()),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: fetchAndUpdateBrain,
        tooltip: '拉取最新数据',
        child: const Icon(Icons.add),
      ),
    );
  }
}

补充说明

  • 测试阶段请先确认Firestore安全规则允许读写,避免权限报错,正式上线前必须配置严格的权限规则,不要长期用全量开放的规则
  • 如果你是通过代码写入的Map数据,且写入时键就是int类型,可以跳过类型转换步骤直接赋值;但通过Firestore控制台手动录入的数据键默认都是字符串,类型转换步骤不能少
  • 如果需要打开页面就自动加载一次数据,直接在initState方法里调用一次fetchAndUpdateBrain()即可
  • 如果后续需要数据实时同步不需要手动点击,可以把get()方法换成snapshots()流监听,配合StreamBuilder实现自动更新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 07:24:24