Flutter中如何在SfCartesianChart中正确加载展示JSON数据
Flutter SfCartesianChart 加载JSON数据异常修复方案
核心问题点
- 接口解析逻辑错误:消费接口返回200成功状态时,错误使用
User模型解析响应体,未提取expense_data字段下的图表数据源 - 数据类型不匹配:图表硬编码绑定
SalesData测试模型,与实际消费数据模型ExpenseDatum不匹配;x轴使用字符串分类轴,与实际DateTime类型的日期字段不适配 - 异步状态缺失:未处理接口请求的异步加载流程,请求完成后未触发组件状态更新,图表始终无法拿到网络数据
修复步骤
1. 补全接口响应模型,修正解析逻辑
新增消费接口对应的响应解析类,替换错误的User模型解析:
// 消费接口响应模型 class ExpenseResponse { final List<ExpenseDatum> expenseData; ExpenseResponse({required this.expenseData}); factory ExpenseResponse.fromJson(Map<String, dynamic> json) { return ExpenseResponse( expenseData: (json['expense_data'] as List? ?? []) .map((item) => ExpenseDatum.fromJson(item)) .toList(), ); } }
修改getExpense方法中200状态码的解析逻辑:
case 200: // 替换原有的User.fromJson解析逻辑 apiResponse.data = ExpenseResponse.fromJson(jsonDecode(response.body)); break;
2. 重构图表组件,适配异步JSON数据
在组件中增加加载状态、数据源存储字段,初始化时触发网络请求,请求完成后更新状态;调整坐标轴类型匹配日期数据,修正数据字段映射关系:
// 记得提前在pubspec.yaml引入intl依赖用于日期格式化,导入路径如下 // import 'package:intl/intl.dart'; class CustomChartData extends StatefulWidget { const CustomChartData({Key? key}) : super(key: key); @override State<CustomChartData> createState() => _CustomChartDataState(); } class _CustomChartDataState extends State<CustomChartData> { late TooltipBehavior _tooltipBehavior; List<ExpenseDatum> _expenseList = []; bool _isLoading = true; @override void initState() { _tooltipBehavior = TooltipBehavior( enable: true, color: AppColors.primaryColor, ); _loadExpenseData(); super.initState(); } Future<void> _loadExpenseData() async { final apiResponse = await getExpense(); setState(() { _isLoading = false; if (apiResponse.data is ExpenseResponse) { _expenseList = (apiResponse.data as ExpenseResponse).expenseData; } }); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; return SizedBox( width: size.width * 0.95, height: size.height * 0.35, child: _isLoading ? const Center(child: CircularProgressIndicator()) : SfCartesianChart( primaryXAxis: DateTimeAxis( dateFormat: DateFormat('yyyy-MM-dd'), intervalType: DateTimeIntervalType.days, ), primaryYAxis: NumericAxis(), legend: const Legend(isVisible: false), tooltipBehavior: _tooltipBehavior, series: <LineSeries<ExpenseDatum, DateTime>>[ LineSeries<ExpenseDatum, DateTime>( dataSource: _expenseList, xValueMapper: (ExpenseDatum data, _) => data.date, yValueMapper: (ExpenseDatum data, _) => data.total, ), ], ), ); } }
3. 优化数据模型空安全
调整ExpenseDatum模型增加空值兜底,避免接口字段缺失导致解析崩溃:
class ExpenseDatum { ExpenseDatum({ required this.date, required this.total, }); final DateTime date; final int total; factory ExpenseDatum.fromJson(Map<String, dynamic> json) => ExpenseDatum( date: DateTime.tryParse(json["date"] ?? '') ?? DateTime.now(), total: json["total"] ?? 0, ); Map<String, dynamic> toJson() => { "date": "${date.year.toString().padLeft(4, '0')}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}", "total": total, }; }
异常效果参考

内容的提问来源于stack exchange,提问作者Al Gabri Riyadh Mohammed
相关产品推荐
相关产品推荐

