【问题标题】:Flutter: Update children state from change in parentFlutter:根据父项的更改更新子状态
【发布时间】: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


【解决方案1】:

结果我继续调试,实际上ResultChart 小部件正在一次又一次地重建,但我从未在子级内部调用setState 函数。我知道初学者错误,但我是 Flutter 新手。

【讨论】:

    猜你喜欢
    • 2021-09-25
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 2016-10-02
    • 2019-11-30
    • 2021-01-12
    • 1970-01-01
    • 2018-07-08
    相关资源
    最近更新 更多