Flutter中如何正确建模Firebase Realtime Database数据并使用?
问题:使用Model类解析Firebase数据后ListView无法显示内容
当前应用前后端代码混写,尝试分离前后端时,使用TestModel解析Firebase数据后,ListView显示为空,打印变量仅返回instance of TestModel,但不使用Model时能正常展示数据。
现有代码情况
TestModel类
class TestModel with ChangeNotifier { String? img; String? path; String? title; TestModel({required this.img, required this.path, required this.title}); factory TestModel.fromJson(Map<dynamic, dynamic> json) { return TestModel( img: json['img'], path: json['path'], title: json['title']); } }
未使用Model时的正常数据获取代码
Future<void> getCategory() async { var nameObect = await _dbRef.child('CategoryMenu').get(); if (nameObect.exists) { var see = nameObect.value as Map; see.entries.map((e) => categoryMenuList.add(e.value)).toList(); setState(() {}); } else { print('Fail'); } }
修改后(使用Model但异常)的代码
Future<void> getCategory() async { var nameObject = await _dbRef.child('CategoryMenu').get(); if (nameObject.exists) { var test = nameObject.value as Map<dynamic, dynamic>; TestModel category = TestModel.fromJson(test); modelList.add(category); setState(() {}); } }
ListView展示代码
ListView.separated( itemCount: modelList.length, itemBuilder: (context, index) { final catItem = modelList[index]; String catIgm = catItem.img.toString(); String title = catItem.title.toString(); String path = catItem.path.toString(); return SizedBox( width: 95, height: 100, child: Text(title) ); }),
解决方法
1. 修正数据解析逻辑(核心问题)
问题根源:nameObject.value是一个包含多个Category节点的Map(key为节点ID,value为单个Category的Map数据),你之前直接把整个大Map传给TestModel.fromJson,导致解析出的对象并非有效Category。需要遍历每个entry,逐个转换为TestModel:
修改后的getCategory方法:
Future<void> getCategory() async { var nameObject = await _dbRef.child('CategoryMenu').get(); if (nameObject.exists) { var test = nameObject.value as Map<dynamic, dynamic>; // 遍历每个Category节点,转换为TestModel并添加到列表 test.entries.forEach((entry) { // entry.value才是单个Category的Map数据 TestModel category = TestModel.fromJson(entry.value); modelList.add(category); }); setState(() {}); } else { print('Fail'); } }
2. 添加toString方法方便调试
给TestModel添加toString方法,这样打印对象时能看到具体字段值,便于排查问题:
class TestModel with ChangeNotifier { String? img; String? path; String? title; TestModel({required this.img, required this.path, required this.title}); factory TestModel.fromJson(Map<dynamic, dynamic> json) { return TestModel( img: json['img'], path: json['path'], title: json['title']); } // 添加toString方法 @override String toString() { return 'TestModel(img: $img, path: $path, title: $title)'; } }
3. 优化ListView的空值处理
避免字段为null时toString()显示"null"字符串,可做空值判断,同时补充缺失的separatorBuilder避免报错:
ListView.separated( itemCount: modelList.length, separatorBuilder: (context, index) => const SizedBox(width: 10), itemBuilder: (context, index) { final catItem = modelList[index]; // 空值处理,默认显示占位文本 String title = catItem.title ?? '无标题'; String catImg = catItem.img ?? ''; String path = catItem.path ?? ''; return SizedBox( width: 95, height: 100, child: Text(title), ); }, ),
内容的提问来源于stack exchange,提问作者Stamp777
相关产品推荐
相关产品推荐

