dart 小部件库(在构建期间调用的setState()或markNeedsBuild())捕获到异常,

wbrvyc0a  于 2023-06-27  发布在  其他
关注(0)|答案(1)|浏览(117)

我在flutter中有一个应用程序,它使用flutter widget以折线图的形式使用WebSocket API调用价格数据。
下面是dart文件名chart.dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:intl/intl.dart';
import 'package:web_socket_channel/io.dart';

const String apiKey =
    "apikey";

class Chart extends StatefulWidget {
  const Chart({Key? key}) : super(key: key);

  @override
  _ChartState createState() => _ChartState();
}

class _ChartState extends State<Chart> {
  late final IOWebSocketChannel channel;
  List<DataPoint> chartData = [];

  @override
  void initState() {
    super.initState();
    channel = IOWebSocketChannel.connect(
      'wss://streamer.cryptocompare.com/v2?api_key=$apiKey',
    );
    subscribeToStream();
  }

  void subscribeToStream() {
    final subRequest = {
      "action": "SubAdd",
      "subs": ["2~Coinbase~BTC~USD"]
    };
    final subRequestJson = jsonEncode(subRequest);
    channel.sink.add(subRequestJson);
  }

  @override
  void dispose() {
    channel.sink.close();
    super.dispose();
  }

  void updateChartData(num price) {
    setState(() {
      chartData.add(DataPoint(DateTime.now().toString(), price.toDouble()));
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: StreamBuilder(
          stream: channel.stream,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              final message = snapshot.data;
              print("Received from Cryptocompare: $message");

              final decodedMessage = jsonDecode(message.toString());
              final messageType = decodedMessage['TYPE'];

              if (messageType == '2') {
                decodedMessage.forEach((key, value) {
                  if (key == 'PRICE') {
                    num price = decodedMessage['PRICE'];
                    updateChartData(price);
                    print('Price: $price');
                  }
                });
              }
            }

            return SfCartesianChart(
              primaryXAxis: CategoryAxis(),
              primaryYAxis: NumericAxis(
                numberFormat: NumberFormat('#.5'), // Display one decimal place
              ),
              series: <LineSeries<DataPoint, String>>[
                LineSeries<DataPoint, String>(
                  dataSource: chartData,
                  xValueMapper: (DataPoint data, _) => data.x,
                  yValueMapper: (DataPoint data, _) => data.y,
                ),
              ],
            );
          },
        ),
      ),
    );
  }
}

class DataPoint {
  final String x;
  final double y;

  DataPoint(this.x, this.y);
}

当我尝试运行它,它显示图表和价格的折线图罚款在第一,然后当数据更新我得到了一个错误关于:Flutter中的Exception Caught By Widgets Library错误,然后它再次更新,它显示图表,然后继续显示图表,然后显示错误,并在每次数据更新时继续。
以下是完整的错误:

setState() or markNeedsBuild()
called during build.
This Chart widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuildO was called
Was:
Chart
The widget which was currently being built when the offending call was made was:
StreamBuilder<dynamic>
See also: https://flutter. dev/ docs/testing/errors

如果你能帮助,这是非常感谢!你可以在评论中问我任何问题。

wlwcrazw

wlwcrazw1#

不需要在updateChartData函数中执行setState,因为您已经在构建函数中获得了更新的数据,因此您的图表UI将使用来自chartData[]的更新数据点构建。
把这个换了

void updateChartData(num price) {
    setState(() {
      chartData.add(DataPoint(DateTime.now().toString(), price.toDouble()));
    });
  }

到这个

void updateChartData(num price) {
     chartData.add(DataPoint(DateTime.now().toString(), price.toDouble()));
  }

相关问题