Open av4625 opened 5 months ago
I have done some further testing and removing checkToShowDot
does not fix the memory leak.
But removing my touchCallback
does fix the memory leak.
I also tried keeping my callbacks for checkToShowDot
and touchCallback
but setting handleBuiltInTouches
to false
, this also doesn't fix the memory leak.
After even more testing:
I found if the callback I provide for touchCallback
contains ref
which is a WidgetRef
for riverpod I get this issue.
I changed the touchCallback
to this (I know its dumb code but I just wanted the bare minimum to make the issue happen):
touchCallback: (final FlTouchEvent ev, final LineTouchResponse? res) {
if (ref != null) {
}
}
I get the memory leak issue. None of my providers contain any FlSpots
so I am very confused at how this is happening.
I have done a memory snap shot and have discovered that it is more than just FlSpots
that are growing. First snap shot is on first draw of the charts and second snap shot is after a 5 second hover back and forth:
There are 4 charts with 2 lines each in this example.
Here is a full main.dart
to reproduce the issue. It is much simpler with only having one chart:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fl_chart/fl_chart.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
body: Column(
children: [
Expanded(child: Chart(),),
Expanded(child: Chart(),),
]
)
)
),
theme: ThemeData(useMaterial3: true),
);
}
}
final testProvider = StateProvider<int>((ref) => 0);
class Chart extends ConsumerWidget {
Chart({super.key});
static const int _numberOfLines = 3;
static const int _numberOfDataPoints = 1500;
@override
Widget build(BuildContext context, WidgetRef ref) {
final int index = ref.watch(testProvider);
return LineChart(
LineChartData(
lineTouchData: LineTouchData(
handleBuiltInTouches: false,
touchSpotThreshold: 20,
touchCallback: (final FlTouchEvent ev, final LineTouchResponse? res) {
ref.read(testProvider.notifier).state = res?.lineBarSpots?.first.spotIndex ?? 0;
},
),
gridData: const FlGridData(show: false),
borderData: FlBorderData(show: false),
lineBarsData: _buildLineData(index),
),
);
}
List<LineChartBarData> _buildLineData(final int index) {
final List<LineChartBarData> lineData = <LineChartBarData>[];
for (int i = 0; i < _numberOfLines; ++i) {
lineData.add(LineChartBarData(
showingIndicators: <int>[index],
dotData: FlDotData(show: false),
spots: () {
return List<FlSpot>.generate(
_numberOfDataPoints,
(index) {
return FlSpot(index.toDouble(), index.toDouble());
}
);
}()
));
}
return lineData;
}
}
You will see that there are 3 lines with 1500
spots each and when you start this app it starts with 4501
FlSpot
objects. Then if you hover this just grows and grows and doesn't stop (other objects grow as well).
Required dependencies:
fl_chart: ^0.67.0
flutter_riverpod: ^2.5.1
Don't make a duplicate issue.
I'm not sure if its the same as this issue as it only happened after I used the callbacks in the title and the example in that issue doesn't use them: https://github.com/imaNNeo/fl_chart/issues/1106
If it is the same I can close this and record it over there.
Describe the bug
I have multiple charts that all show relating data. The data in this example has around 1500 points per line and I have tested up to 5 lines, so is fairly large. When I hover over one I wanted to show "spots" on the others.
To do this I added a
touchCallback
that saves the hovered spot locations in a riverpodNotifierProvider
. All charts watch this and then in theircheckToShowDot
it checks for the spots that relate to the hover data in theNotifierProvider
and then draws them.I have noticed that the flutter app started using lots of RAM after I added this hover functionality. I have seen over 2Gb and climbing in apples activity monitor. The app starts between 200-300mb. I opened the memory page of devtools and it shows that there where millions of FlSpot objects and they climb in numbers fast when hovering on a chart. It suffers from frame jank and gets slower and slower the more you hover until it becomes unusable.
It is possible I'm misusing the API as I'm new to Dart/Flutter.
To Reproduce
This is one of the 4 charts in the video (the middle one of the 3 on the right side). All 4 charts are almost identical to this.
These two functions are in a parent class:
Before adding the two callbacks I mention above I just had this and the FlSpots never change from
27093
for 5 lines:Screenshots
Video of the charts and how they work (you can see there is major frame jank at times): https://github.com/imaNNeo/fl_chart/assets/19472253/e42fbd6f-311e-435f-9c4f-a7cd1b5db3b0
A snap of the number of FlSpot objects:
Hovered for about 10 seconds and took a snap of the number of FlSpot objects again:
Versions