Skip to content

Commit

Permalink
Remove caching system for calculated minX, maxX, minY and maxY values…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
imaNNeo committed Jun 21, 2024
1 parent 514bd9e commit f0539ed
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 114 deletions.
10 changes: 5 additions & 5 deletions lib/src/chart/line_chart/line_chart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ class _LineChartState extends AnimatedWidgetBaseState<LineChart> {
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,
);
}

Expand Down
62 changes: 7 additions & 55 deletions lib/src/chart/line_chart/line_chart_helper.dart
Original file line number Diff line number Diff line change
@@ -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<LineChartBarData>]
///
/// We use it to prevent redundant calculations
final Map<ListWrapper<LineChartBarData>, 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<LineChartBarData> 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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<Object?> 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);
}
}
8 changes: 4 additions & 4 deletions repo_files/documentations/line_chart.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
55 changes: 15 additions & 40 deletions test/chart/line_chart/line_chart_helper_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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', () {
Expand All @@ -49,22 +28,20 @@ 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', () {
final lineChartHelper = LineChartHelper();
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);
});

Expand All @@ -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', () {
Expand All @@ -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));
});
});
}
20 changes: 10 additions & 10 deletions test/chart/line_chart/line_chart_painter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ void main() {
);

final lineChartBarsData = <LineChartBarData>[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(
Expand Down Expand Up @@ -147,15 +147,15 @@ void main() {
);

final lineChartBarsData = <LineChartBarData>[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(
Expand Down

0 comments on commit f0539ed

Please sign in to comment.