0

I am creating a real time graph in flutter using SyncFusion Charts in flutter. The number of line graphs which will be displayed in that chart depends on runtime, hence I created a method which would add the LineSeries<DataForGraph, double> to the List<ChartSeries> dynamically where DataForGraph is a class which contains time and value used in the graph. Now, since each LineSeries will require a separate controller (since different line graphs will have different values at the same time), I created a late List<ChartSeriesController> chartSeriesControllerList which will contain the number of ChartSeriesController objects depending on how many graphs to show during runtime. However, flutter gives me this error:

E/flutter ( 3535): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field '_chartSeriesController@50005135' has not been initialized.
E/flutter ( 3535): #0      _LiveChartState.updateDataSource (package:scan_tabview/widgets/live_chart.dart:189:7)
E/flutter ( 3535): <asynchronous suspension>

My DataForGraph class:

class DataForGraph {
  final double time;
  final double value;
  DataForGraph(this.time, this.value);
}

I did try to initialize it during declaration however, the ChartSeriesController() constructor takes an argument seriesRenderer which I don't know how (and if) to get. How can I create multiple ChartSeriesControllers?

Omkar Phadke
  • 27
  • 1
  • 7

1 Answers1

0

We suspect that you have not assigned the controller value in the onRendererCreated callback like in the below code snippet which is the reason for getting a late initialization error.

LineSeries<_ChartData, int>(
  onRendererCreated: (ChartSeriesController controller) {
    chartSeriesController = controller;
  },
 // Other required properties.
)

And we have created the list of ChartSeriesController and updated the list dynamically for each line series so that it will work properly, and we have attached the sample code snippet below for your reference.

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:syncfusion_flutter_core/core.dart';

void main() {
  return runApp(ChartApp());
}

class ChartApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Chart Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: LiveLineChart(),
    );
  }
}

class LiveLineChart extends StatefulWidget {
  /// Creates the realtime line chart sample.
  const LiveLineChart({Key? key}) : super(key: key);

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

/// State class of the realtime line chart.
class _LiveLineChartState extends State<LiveLineChart> {
  _LiveLineChartState() {
    timer = Timer.periodic(const Duration(milliseconds: 100), (_timer) {
      for (int i = 0; i < 4; i++) {
        _updateDataSource(_timer, chartData[i] as List<_ChartData>,
            chartSeriesController![i]);
      }
    });
  }

  Timer? timer;
  int seriesCount = 2;

  List<List<dynamic>> chartData = [];
  List<_ChartData> chartData1 = [];
  List<_ChartData> chartData2 = [];
  List<_ChartData> chartData3 = [];
  List<_ChartData> chartData4 = [];
  late int count;
  ChartSeriesController? _chartSeriesController1;
  ChartSeriesController? _chartSeriesController2;
  ChartSeriesController? _chartSeriesController3;
  ChartSeriesController? _chartSeriesController4;
  List<dynamic>? chartSeriesController = [];

  @override
  void dispose() {
    timer?.cancel();
    chartData[0].clear();
    chartData[1].clear();
    chartData[2].clear();
    chartData[3].clear();
    super.dispose();
  }

  @override
  void initState() {
    count = 19;
    chartSeriesController = <dynamic>[
      _chartSeriesController1,
      _chartSeriesController2,
      _chartSeriesController3,
      _chartSeriesController4
    ];
    chartData = <List<dynamic>>[chartData1, chartData2, chartData3, chartData4];
    chartData[0] = <_ChartData>[
      _ChartData(0, 42),
    ];
    chartData[1] = <_ChartData>[
      _ChartData(0, 42),
    ];
    chartData[2] = <_ChartData>[
      _ChartData(0, 42),
    ];
    chartData[3] = <_ChartData>[
      _ChartData(0, 42),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(), body: _buildLiveLineChart());
  }

  /// Returns the realtime Cartesian line chart.
  SfCartesianChart _buildLiveLineChart() {
    return SfCartesianChart(
        plotAreaBorderWidth: 0,
        primaryXAxis:
            NumericAxis(majorGridLines: const MajorGridLines(width: 0)),
        primaryYAxis: NumericAxis(
            axisLine: const AxisLine(width: 0),
            majorTickLines: const MajorTickLines(size: 0)),
        series: getLineSeries());
  }

  List<LineSeries<_ChartData, num>> getLineSeries() {
    List<LineSeries<_ChartData, num>> lineSeries = [];
    for (int i = 0; i < 4; i++) {
      lineSeries.add(LineSeries<_ChartData, int>(
        onRendererCreated: (ChartSeriesController controller) {
          chartSeriesController![i] = controller;
        },
        dataSource: chartData[i] as List<_ChartData>,
        xValueMapper: (_ChartData sales, _) => sales.country,
        yValueMapper: (_ChartData sales, _) => sales.sales,
        animationDuration: 0,
      ));
    }
    return lineSeries;
  }

  ///Continously updating the data source based on timer
  void _updateDataSource(Timer timer, List<_ChartData> chartData,
      ChartSeriesController _chartSeriesController) {
    chartData.add(_ChartData(count, _getRandomInt(10, 100)));
    if (chartData.length == 20) {
      chartData.removeAt(0);
      _chartSeriesController.updateDataSource(
        addedDataIndexes: <int>[chartData.length - 1],
        removedDataIndexes: <int>[0],
      );
    } else {
      _chartSeriesController.updateDataSource(
        addedDataIndexes: <int>[chartData.length - 1],
      );
    }
    count = count + 1;
  }

  ///Get the random data
  int _getRandomInt(int min, int max) {
    final Random _random = Random();
    return min + _random.nextInt(max - min);
  }
}

/// Private calss for storing the chart series data points.
class _ChartData {
  _ChartData(this.country, this.sales);
  final int country;
  final num sales;
}
yuva
  • 436
  • 4
  • 9