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

Flutter读取Firebase Realtime Database数据时出现类型不匹配报错

问题根源

你贴出的运行报错如下:
Error message
对应Firebase Realtime Database存储结构如下:
Realtime Firebase

报错核心是3处类型处理错误:

  • 对Firebase Realtime Database的返回值处理逻辑完全错误:DataSnapshot.value本身就会返回Dart原生的Map/List类型结构化数据,不是JSON格式字符串,你代码里强行将其as String?再调用json.decode,直接触发了类型转换异常,和报错信息type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'String?'完全对应。
  • 数据模型的icon字段解析逻辑错误:你数据库中存储的是Material图标对应的codePoint整数值,直接赋值给IconData?类型会触发类型不匹配。
  • FutureBuilder未指定泛型,快照数据无类型校验,容易触发隐式类型错误。
修复方案

1. 重写数据请求方法,移除多余的JSON解码逻辑

替换原有firebaseCalls方法:

Future<List<Menu>> firebaseCalls(DatabaseReference ref) async {
  DataSnapshot dataSnapshot = await ref.child('Task').get();
  // 直接拿Firebase返回的列表数据,无需JSON解码
  final rawList = dataSnapshot.value as List<dynamic>;
  return rawList
      .map((e) => Menu.fromJson(Map<String, dynamic>.from(e as Map)))
      .toList();
}

2. 修正数据模型的icon解析和subMenu类型处理

替换datamodel.dart中全部代码:

import 'package:flutter/material.dart';
class Menu {
  String? name;
  IconData? icon;
  int? font;
  List<Menu>? subMenu = [];

  Menu({this.name, this.subMenu, this.icon, this.font});
  
  Menu.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    font = json['font'];
    // 将存储的int类型codePoint转换为IconData实例
    if (json['icon'] != null) {
      icon = IconData(json['icon'] as int, fontFamily: 'MaterialIcons');
    }
    if (json['subMenu'] != null) {
      subMenu = [];
      (json['subMenu'] as List).forEach((v) {
        subMenu?.add(Menu.fromJson(Map<String, dynamic>.from(v as Map)));
      });
    }
  }
}

3. 给FutureBuilder添加泛型,补全类型校验

替换原有FutureBuilder部分代码:

body: FutureBuilder<List<Menu>>(
  future: firebaseCalls(ref),
  builder: (BuildContext context, AsyncSnapshot<List<Menu>> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return const Text('Press button to start');
      case ConnectionState.waiting:
        return const Text('Loading....');
      default:
        if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        }
        final menuData = snapshot.data!;
        return ListView.builder(
          itemCount: menuData.length,
          itemBuilder: (BuildContext context, int index) =>
              _buildTiles(menuData[index]),
        );
    }
  },
)
验证说明

从你贴出的数据库结构截图来看,节点存储格式和修复后代码的解析逻辑完全匹配,替换后即可正常加载数据渲染列表。如果后续要存储自定义对象到Realtime Database,不需要手动转JSON字符串存储,直接存原生Map/List结构即可,SDK会自动完成序列化转换。


内容的提问来源于stack exchange,提问作者safaa al-wajidi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:09:19