From f0539edfbae554079c4a57ca82bb6d1dfa09d2d2 Mon Sep 17 00:00:00 2001 From: imaNNeoFighT Date: Fri, 21 Jun 2024 10:56:48 +0200 Subject: [PATCH] Remove caching system for calculated minX, maxX, minY and maxY values in the lineChart, it caused some memory issues, we will remove the caching for now, but later we have to move the calculations into the renderers to keep and update the values when the data changes. --- lib/src/chart/line_chart/line_chart.dart | 10 +-- .../chart/line_chart/line_chart_helper.dart | 62 +++---------------- repo_files/documentations/line_chart.md | 8 +-- .../line_chart/line_chart_helper_test.dart | 55 +++++----------- .../line_chart/line_chart_painter_test.dart | 20 +++--- 5 files changed, 41 insertions(+), 114 deletions(-) diff --git a/lib/src/chart/line_chart/line_chart.dart b/lib/src/chart/line_chart/line_chart.dart index f36321df9d..01eb3eb0b1 100644 --- a/lib/src/chart/line_chart/line_chart.dart +++ b/lib/src/chart/line_chart/line_chart.dart @@ -87,14 +87,14 @@ class _LineChartState extends AnimatedWidgetBaseState { newData.maxX.isNaN || newData.minY.isNaN || newData.maxY.isNaN) { - final values = _lineChartHelper.calculateMaxAxisValues( + final (minX, maxX, minY, maxY) = _lineChartHelper.calculateMaxAxisValues( newData.lineBarsData, ); newData = newData.copyWith( - minX: newData.minX.isNaN ? values.minX : newData.minX, - maxX: newData.maxX.isNaN ? values.maxX : newData.maxX, - minY: newData.minY.isNaN ? values.minY : newData.minY, - maxY: newData.maxY.isNaN ? values.maxY : newData.maxY, + minX: newData.minX.isNaN ? minX : newData.minX, + maxX: newData.maxX.isNaN ? maxX : newData.maxX, + minY: newData.minY.isNaN ? minY : newData.minY, + maxY: newData.maxY.isNaN ? maxY : newData.maxY, ); } diff --git a/lib/src/chart/line_chart/line_chart_helper.dart b/lib/src/chart/line_chart/line_chart_helper.dart index 90e388f036..0a37d5543e 100644 --- a/lib/src/chart/line_chart/line_chart_helper.dart +++ b/lib/src/chart/line_chart/line_chart_helper.dart @@ -1,26 +1,15 @@ -import 'package:equatable/equatable.dart'; import 'package:fl_chart/fl_chart.dart'; -import 'package:fl_chart/src/utils/list_wrapper.dart'; /// Contains anything that helps LineChart works class LineChartHelper { - /// Contains List of cached results, base on [List] - /// - /// We use it to prevent redundant calculations - final Map, LineChartMinMaxAxisValues> - _cachedResults = {}; - LineChartMinMaxAxisValues calculateMaxAxisValues( + /// Calculates the [minX], [maxX], [minY], and [maxY] values of + /// the provided [lineBarsData]. + (double minX, double maxX, double minY, double maxY) calculateMaxAxisValues( List lineBarsData, ) { if (lineBarsData.isEmpty) { - return const LineChartMinMaxAxisValues(0, 0, 0, 0); - } - - final listWrapper = lineBarsData.toWrapperClass(); - - if (_cachedResults.containsKey(listWrapper)) { - return _cachedResults[listWrapper]!.copyWith(readFromCache: true); + return (0, 0, 0, 0); } final LineChartBarData lineBarData; @@ -29,7 +18,7 @@ class LineChartHelper { lineBarsData.firstWhere((element) => element.spots.isNotEmpty); } catch (e) { // There is no lineBarData with at least one spot - return const LineChartMinMaxAxisValues(0, 0, 0, 0); + return (0, 0, 0, 0); } final FlSpot firstValidSpot; @@ -38,7 +27,7 @@ class LineChartHelper { lineBarData.spots.firstWhere((element) => element != FlSpot.nullSpot); } catch (e) { // There is no valid spot - return const LineChartMinMaxAxisValues(0, 0, 0, 0); + return (0, 0, 0, 0); } var minX = firstValidSpot.x; @@ -68,43 +57,6 @@ class LineChartHelper { } } - final result = LineChartMinMaxAxisValues(minX, maxX, minY, maxY); - _cachedResults[listWrapper] = result; - return result; - } -} - -/// Holds minX, maxX, minY, and maxY for use in [LineChartData] -class LineChartMinMaxAxisValues with EquatableMixin { - const LineChartMinMaxAxisValues( - this.minX, - this.maxX, - this.minY, - this.maxY, { - this.readFromCache = false, - }); - final double minX; - final double maxX; - final double minY; - final double maxY; - final bool readFromCache; - - @override - List get props => [minX, maxX, minY, maxY, readFromCache]; - - LineChartMinMaxAxisValues copyWith({ - double? minX, - double? maxX, - double? minY, - double? maxY, - bool? readFromCache, - }) { - return LineChartMinMaxAxisValues( - minX ?? this.minX, - maxX ?? this.maxX, - minY ?? this.minY, - maxY ?? this.maxY, - readFromCache: readFromCache ?? this.readFromCache, - ); + return (minX, maxX, minY, maxY); } } diff --git a/repo_files/documentations/line_chart.md b/repo_files/documentations/line_chart.md index be5ab9dbfe..65b4e21a6f 100644 --- a/repo_files/documentations/line_chart.md +++ b/repo_files/documentations/line_chart.md @@ -26,11 +26,11 @@ When you change the chart's state, it animates to the new state internally (usin |showingTooltipIndicators| show the tooltip based on provided list of [LineBarSpot](#LineBarSpot), The point is that you need to disable touches to show these tooltips manually| [] | |gridData| check the [FlGridData](base_chart.md#FlGridData)|FlGridData()| |borderData| check the [FlBorderData](base_chart.md#FlBorderData)|FlBorderData()| -|minX| gets minimum x of x axis, if null, value will read from the input lineBars |null| -|maxX| gets maximum x of x axis, if null, value will read from the input lineBars | null| +|minX| gets minimum x of x axis, if null, value will read from the input lineBars (But it is more performant if you provide them)|null| +|maxX| gets maximum x of x axis, if null, value will read from the input lineBars (But it is more performant if you provide them)| null| |baselineX| defines the baseline of x-axis | 0| -|minY| gets minimum y of y axis, if null, value will read from the input lineBars | null| -|maxY| gets maximum y of y axis, if null, value will read from the input lineBars | null| +|minY| gets minimum y of y axis, if null, value will read from the input lineBars (But it is more performant if you provide them)| null| +|maxY| gets maximum y of y axis, if null, value will read from the input lineBars (But it is more performant if you provide them)| null| |baselineY| defines the baseline of y-axis | 0| |clipData| clip the chart to the border (prevent drawing outside the border) | FlClipData.none()| |backgroundColor| a background color which is drawn behind th chart| null | diff --git a/test/chart/line_chart/line_chart_helper_test.dart b/test/chart/line_chart/line_chart_helper_test.dart index 341e35f27d..155e6cf800 100644 --- a/test/chart/line_chart/line_chart_helper_test.dart +++ b/test/chart/line_chart/line_chart_helper_test.dart @@ -6,36 +6,15 @@ import '../data_pool.dart'; void main() { group('Check caching of LineChartHelper.calculateMaxAxisValues', () { - test('Test read from cache1', () { - final lineChartHelper = LineChartHelper(); - final lineBars1 = [lineChartBarData1]; - final result1 = lineChartHelper.calculateMaxAxisValues(lineBars1); - - final lineBars2 = [lineChartBarData2]; - final result2 = lineChartHelper.calculateMaxAxisValues(lineBars2); - - expect(result1.readFromCache, false); - expect(result2.readFromCache, false); - }); - - test('Test read from cache2', () { - final lineChartHelper = LineChartHelper(); - final lineBars = [lineChartBarData1, lineChartBarData2]; - final lineBarsClone = [lineChartBarData1Clone, lineChartBarData2]; - final result1 = lineChartHelper.calculateMaxAxisValues(lineBars); - final result2 = lineChartHelper.calculateMaxAxisValues(lineBarsClone); - expect(result1.readFromCache, false); - expect(result2.readFromCache, true); - }); - test('Test validity 1', () { final lineChartHelper = LineChartHelper(); final lineBars = [lineChartBarData1, lineChartBarData2]; - final result = lineChartHelper.calculateMaxAxisValues(lineBars); - expect(result.minX, 1); - expect(result.maxX, 4); - expect(result.minY, 1); - expect(result.maxY, 2); + final (minX, maxX, minY, maxY) = + lineChartHelper.calculateMaxAxisValues(lineBars); + expect(minX, 1); + expect(maxX, 4); + expect(minY, 1); + expect(maxY, 2); }); test('Test validity 2', () { @@ -49,11 +28,12 @@ void main() { ], ), ]; - final result = lineChartHelper.calculateMaxAxisValues(lineBars); - expect(result.minX, -3); - expect(result.maxX, 14); - expect(result.minY, -10); - expect(result.maxY, 50); + final (minX, maxX, minY, maxY) = + lineChartHelper.calculateMaxAxisValues(lineBars); + expect(minX, -3); + expect(maxX, 14); + expect(minY, -10); + expect(maxY, 50); }); test('Test equality', () { @@ -61,10 +41,7 @@ void main() { final lineBars = [lineChartBarData1, lineChartBarData2]; final lineBarsClone = [lineChartBarData1Clone, lineChartBarData2]; final result1 = lineChartHelper.calculateMaxAxisValues(lineBars); - final result2 = - lineChartHelper.calculateMaxAxisValues(lineBarsClone).copyWith( - readFromCache: false, - ); + final result2 = lineChartHelper.calculateMaxAxisValues(lineBarsClone); expect(result1, result2); }); @@ -80,8 +57,7 @@ void main() { ], ), ]; - final result1 = lineChartHelper.calculateMaxAxisValues(lineBars); - expect(result1, const LineChartMinMaxAxisValues(0, 0, 0, 0)); + expect(lineChartHelper.calculateMaxAxisValues(lineBars), (0, 0, 0, 0)); }); test('Test null spot 2', () { @@ -96,8 +72,7 @@ void main() { ], ), ]; - final result1 = lineChartHelper.calculateMaxAxisValues(lineBars); - expect(result1, const LineChartMinMaxAxisValues(-1, 4, -3, 5)); + expect(lineChartHelper.calculateMaxAxisValues(lineBars), (-1, 4, -3, 5)); }); }); } diff --git a/test/chart/line_chart/line_chart_painter_test.dart b/test/chart/line_chart/line_chart_painter_test.dart index 7cad6c0809..19925557fb 100644 --- a/test/chart/line_chart/line_chart_painter_test.dart +++ b/test/chart/line_chart/line_chart_painter_test.dart @@ -48,15 +48,15 @@ void main() { ); final lineChartBarsData = [bar1, bar2]; - final axisValues = LineChartHelper().calculateMaxAxisValues( + final (minX, maxX, minY, maxY) = LineChartHelper().calculateMaxAxisValues( lineChartBarsData, ); final data = LineChartData( - minX: axisValues.minX, - maxX: axisValues.maxX, - minY: axisValues.minY, - maxY: axisValues.maxY, + minX: minX, + maxX: maxX, + minY: minY, + maxY: maxY, lineBarsData: lineChartBarsData, clipData: const FlClipData.all(), extraLinesData: ExtraLinesData( @@ -147,15 +147,15 @@ void main() { ); final lineChartBarsData = [bar1, bar2]; - final axisValues = LineChartHelper().calculateMaxAxisValues( + final (minX, maxX, minY, maxY) = LineChartHelper().calculateMaxAxisValues( lineChartBarsData, ); final data = LineChartData( - minX: axisValues.minX, - maxX: axisValues.maxX, - minY: axisValues.minY, - maxY: axisValues.maxY, + minX: minX, + maxX: maxX, + minY: minY, + maxY: maxY, lineBarsData: lineChartBarsData, clipData: const FlClipData.all(), lineTouchData: LineTouchData(