【发布时间】:2021-12-09 04:42:21
【问题描述】:
注意:代码可能看起来很长,但对于这个问题,您不需要了解它的每个部分。
我有一个应用程序,它从 API 获取数据以使用它构建图表。我使用 Syncfusion 笛卡尔图表包。这是一个经济指标,所以它带有一个日期和一个值,例如:
[[2015 Oct, 0.24],[2015 Nov, 0.26],[2015 Dec, 0.32],[2016 Jan, 0.35],[2016 Feb, 0.40],[2016 Mar, 0.48]]
所以,一旦数据到达(它有一个等待来自 HTTP 请求的数据的加载屏幕),我用它构建图表。
所以在这种情况下,我的 Parent 小部件被命名为 ChartScreen。代码如下:
class ChartScreen extends StatefulWidget {
@override
State<ChartScreen> createState() => _ChartScreenState();
}
class _ChartScreenState extends State<ChartScreen> {
String dropdownValue = '';
initState() {
dropdownValue = '2016';
return super.initState();
}
@override
Widget build(BuildContext context) {
final enterpriseProvider = Provider.of<EnterpriseProvider>(context);
final resp = enterpriseProvider.indicator;
List<IpcData> data = _createIpcList(resp, dropdownValue);
if( data.length == 0 ) {
return Scaffold(
appBar: AppBar(
title: Text('Obteniendo datos...'),
),
body: Container(
color: Colors.black,
width: double.infinity,
height: double.infinity,
child: Center(
child: CircularProgressIndicator(),
),
),
);
}
return
Scaffold(
appBar: AppBar(
title: Text('IPC'),
actions:[
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButton(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.white,
),
onChanged: (String? newValue) {
dropdownValue = newValue!;
data = _createIpcList(resp, dropdownValue);
setState(() {});
},
items: <String>['2016', '2017', '2018', '2019']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList()
),
)
]
),
drawer: SideMenu(),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Container(
child: ResultChart( formattedData: data )###############################
),
),
],
)
);
}
_createIpcList(List<List<dynamic>> resp, [String? year]) {
print('EL AÑOO');
print(year);
List<IpcData>finalList = [];
if(resp.length != 0) {
for(int i = 0; i < resp.length; i++) {
try {
resp[i][0] = DateFormat.yMMM().format(DateTime.parse(resp[i][0]));
} catch(e) {}
}
}
List<IpcData> ipcList = resp.map((e) => IpcData(e[0], e[1])).toList();
if (year!= null) {
for(int i = 0; i < ipcList.length; i++){
if (ipcList[i].date.contains(year)){
finalList.add(ipcList[i]);
}
}
}
return finalList;
}
}
我使用 _createIpcList 格式化 JSON 数据,以便图表可以使用它。我突出显示了我调用要更新其状态的孩子的行。但在此之前,您可以看到我添加了一个下拉菜单,以从(硬编码)列表中选择一年。当下拉菜单中选择的项目发生变化时(参见 onChanged),我调用 SetState 并将“年份参数”传递给 _createIpcList,它会过滤数据并返回属于所选年份的项目。这是子代码:
class ResultChart extends StatefulWidget {
final List<IpcData> formattedData;
const ResultChart({
Key? key,
required this.formattedData
}) : super(key: key);
@override
_ResultChartState createState() => _ResultChartState();
}
class _ResultChartState extends State<ResultChart> {
late List<IpcData> _chartData;
@override
void initState() {
_chartData = widget.formattedData;
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
backgroundColor: Colors.black,
enableAxisAnimation: false,
trackballBehavior: TrackballBehavior(
enable: true,
shouldAlwaysShow: true,
tooltipSettings: InteractiveTooltip(
borderWidth: 2,
borderColor: Colors.grey,
color: Colors.grey[400],
format: 'point.x : point.y'
)
),
zoomPanBehavior: ZoomPanBehavior(
enablePanning: true,
enablePinching: true,
enableDoubleTapZooming: true,
zoomMode: ZoomMode.xy,
),
primaryXAxis: CategoryAxis(
labelRotation: 90,
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey[400]
),
axisLine: AxisLine(
width: 2,
color: Colors.grey
),
majorGridLines: MajorGridLines(width: 1),
),
primaryYAxis: NumericAxis(
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey[400]
),
axisLine: AxisLine(
width: 2,
color: Colors.grey
),
title: AxisTitle( text: 'IPC', textStyle: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
majorGridLines: MajorGridLines(width: 1),
),
series: <ChartSeries>[
LineSeries<IpcData, String>(
color: Colors.blue,
dataSource: _chartData,
xValueMapper: (IpcData data, _) => data.date,
yValueMapper: (IpcData data, _) => data.value
)
],)
);
}
}
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
}
我的问题是,无论我选择哪一年,图表都不会改变。我知道“dropdownValue”发生了变化,因为我使用了一些 prints() 进行了调试,但我不知道如何重建或设置 ResultChart 小部件的状态。
【问题讨论】:
-
你为什么不更新
setState里面的值,这里是dropdownValue = newValue!; data = _createIpcList(resp, dropdownValue); setState(() {}); -
哦,我知道它看起来很奇怪,但它仍然有效。我之前在 setstate 中拥有它并且可以以任何一种方式工作。我可以保证这一点,因为 _createIpcList 中的打印每次更改时都会显示正确的值
标签: flutter dart stateful statefulwidget