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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:06:35