如何在Flutter Syncfusion Flutter Charts中展示JSON数据?解决参数类型不匹配错误
首先看你遇到的类型错误:The argument type 'String Function(SensorData, int, dynamic)' can't be assigned to the parameter type 'String Function(SensorData, int)',原因很直接——你给xValueMapper和yValueMapper传的回调函数参数数量不对。Syncfusion的这两个映射函数只接受两个参数:数据对象本身和索引,但你写了三个参数(SensorData, sensors, _),而且参数命名也搞混了(第一个参数是类型,没给变量名,第二个变量名sensors其实应该是数据对象)。
除了这个类型错误,你的代码还有几个关键问题需要修正,才能正确从API获取数据并渲染图表:
1. 修正X/Y值映射函数的签名
把xValueMapper和yValueMapper改成正确的参数结构,同时注意X轴是CategoryAxis,需要传入字符串类型的时间,所以要把DateTime转成字符串:
xValueMapper: (SensorData data, int index) => data.timeStamp.toString(), yValueMapper: (SensorData data, int index) => data.sensorValue,
2. 修复API数据获取与解析逻辑
你的loadSensorData函数完全没有调用fetchUsers来获取API数据,而且直接用json.decode(toString())是无效的。另外,Thingspeak的API返回结构是包含feeds数组的对象,你需要正确解析这个数组,同时处理字段名不匹配的问题:
- Thingspeak里的时间字段是
created_at,不是timeStamp - 湿度值字段是
field1,不是SensorValue - 接口返回的
field1是字符串,需要转成int类型
修正后的loadSensorData和fetchUsers:
Future loadSensorData() async { try { final responseBody = await fetchUsers(); final jsonResponse = json.decode(responseBody); // 从API返回的feeds数组中解析数据 setState(() { chartData = (jsonResponse['feeds'] as List) .map((feed) => SensorData.fromJson(feed)) .toList(); }); } catch (e) { print('加载数据出错: $e'); } } Future<String> fetchUsers() async { var url = Uri.parse('https://api.thingspeak.com/channels/960293/fields/1.json'); http.Response response = await http.get(url); // 检查响应状态码,确保请求成功 if (response.statusCode == 200) { return response.body; } else { throw Exception('请求API失败,状态码: ${response.statusCode}'); } }
3. 修正SensorData的fromJson工厂方法
根据Thingspeak的字段名调整解析逻辑,并处理类型转换:
class SensorData { SensorData({ required this.timeStamp, required this.sensorValue, }); DateTime timeStamp; int sensorValue; factory SensorData.fromJson(Map<String, dynamic> json) { return SensorData( // 把字符串时间转成DateTime timeStamp: DateTime.parse(json['created_at']), // 把字符串值转成int,注意处理可能的null值 sensorValue: int.parse(json['field1'] ?? '0'), ); } }
完整修正后的代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:http/http.dart' as http; class LineChartHum extends StatefulWidget { @override _LineChartHumState createState() => _LineChartHumState(); } class _LineChartHumState extends State<LineChartHum> { List<SensorData> chartData = []; @override void initState() { super.initState(); loadSensorData(); } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( margin: EdgeInsets.all(16), height: 300, child: SfCartesianChart( zoomPanBehavior: ZoomPanBehavior( enableDoubleTapZooming: true, enablePanning: true, enableSelectionZooming: true, enableMouseWheelZooming: true, ), primaryXAxis: CategoryAxis( // 可以设置标签旋转,避免重叠 labelRotation: 45, ), title: ChartTitle(text: 'Humidity Sensor'), tooltipBehavior: TooltipBehavior(enable: true), series: <LineSeries<SensorData, String>>[ LineSeries<SensorData, String>( dataSource: chartData, xValueMapper: (SensorData data, int index) => data.timeStamp.toString(), yValueMapper: (SensorData data, int index) => data.sensorValue, // 可选:添加数据点标记 markerSettings: MarkerSettings(isVisible: true), ) ])) ], ), ); } Future loadSensorData() async { try { final responseBody = await fetchUsers(); final jsonResponse = json.decode(responseBody); setState(() { chartData = (jsonResponse['feeds'] as List) .map((feed) => SensorData.fromJson(feed)) .toList(); }); } catch (e) { print('加载数据出错: $e'); } } } Future<String> fetchUsers() async { var url = Uri.parse('https://api.thingspeak.com/channels/960293/fields/1.json'); http.Response response = await http.get(url); if (response.statusCode == 200) { return response.body; } else { throw Exception('请求API失败,状态码: ${response.statusCode}'); } } class SensorData { SensorData({ required this.timeStamp, required this.sensorValue, }); DateTime timeStamp; int sensorValue; factory SensorData.fromJson(Map<String, dynamic> json) { return SensorData( timeStamp: DateTime.parse(json['created_at']), sensorValue: int.parse(json['field1'] ?? '0'), ); } }
这样修改后,你的图表应该能正确加载并显示Thingspeak的湿度数据了。另外我还加了一些优化,比如X轴标签旋转、数据点标记,以及错误捕获逻辑,让代码更健壮。
内容的提问来源于stack exchange,提问作者isofttechn

