Flutter读取Firebase Realtime Database数据时出现类型不匹配报错
问题根源
你贴出的运行报错如下:
对应Firebase Realtime Database存储结构如下:
报错核心是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
相关产品推荐
相关产品推荐

