I want to have more than one chart and when I hover on one I want it to update and show the hover on the other charts.
To achieve this I store the hover “state” using riverpod
and then all charts listen for it and then draw with the hovered location. I use the touchCallback
provided by fl_chart
to make this work.
Am I miss-using riverpod
or fl_charts
API’s with this method or is it a bug in fl_chart
? I am getting a bad memory leak of fl_chart
objects doing this. The objects grow quickly when hovering and don’t reduce.
Its easy to see the FlSpot objects as they grow so quick, it starts with 4501 objects, 3 lines of 1500 points. Then hovering makes these increase into the millions fast. It’s not only these objects, it is also other fl_chart
objects like titles etc.
Below is a simpler full project that reproduces the issue with 2 charts.
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;
}
}