Flutter使用Provider无法设置从Firebase Database获取的数据如何解决
问题原因及修复方案
你遇到的类型转换错误不是ChartHistoricalData.fromJson方法的问题,是Firebase Realtime Database返回的数据结构类型和页面请求逻辑两个问题共同导致的:
- Firebase返回的嵌套字典默认是
Map<Object?, Object?>类型,你直接用as Map<String, dynamic>强转就会抛出类型不匹配的错误 - 你把异步请求方法
fetchHistoricalStockData直接写在build方法里,每次页面重绘都会触发重复请求,而且第一次build的时候请求还没完成,所以你打印的histChartData自然是空的
1. 修复Provider中的数据转换逻辑
你需要先把拿到的Object类型的map显式转换成Map<String, dynamic>,修改后的fetchHistoricalStockData方法如下:
Future<void> fetchHistoricalStockData(DatabaseReference ref) async { final dataSnapshot = await ref.once(); final rawHistoricalList = dataSnapshot.value['SBIN_Historical'] as List; _histChartData = rawHistoricalList.map((rawItem) { // 先把Object?类型的map转成Map<String, dynamic> final itemMap = Map<String, dynamic>.from(rawItem as Map); return ChartHistoricalData.fromJson(itemMap); }).toList(); notifyListeners(); }
2. 修复页面请求调用逻辑
不要把异步请求放在build方法里,移到initState生命周期里只执行一次:
class _ChartState extends State<SBINChart> { final fb = FirebaseDatabase.instance; late final DatabaseReference ref; @override void initState() { super.initState(); ref = fb.reference(); // 只在页面初始化的时候发起一次请求 WidgetsBinding.instance.addPostFrameCallback((_) { context.read<StockProvider>().fetchHistoricalStockData(ref); }); } @override Widget build(BuildContext context) { // 这里直接监听状态变化即可 final histData = context.watch<StockProvider>().histChartData; print(histData); // 请求完成后就会拿到非空数据 // 后续渲染逻辑可以加个判断,数据为空的时候显示加载中 if (histData.isEmpty) { return const Center(child: CircularProgressIndicator()); } // 你的图表渲染逻辑 return ...; } }
3. 可选优化:模型类空安全处理
你可以给fromJson方法里的数值也加个类型转换,避免Firebase返回int类型数值时报错:
ChartHistoricalData.fromJson(Map<String, dynamic> json) { x = DateTime.parse(json['date'] as String); open = (json['open'] as num).toDouble(); high = (json['high'] as num).toDouble(); low = (json['low'] as num).toDouble(); close = (json['close'] as num).toDouble(); }
内容的提问来源于stack exchange,提问作者dev1ce
相关产品推荐
相关产品推荐

