imaNNeo / imaNNeo/fl_chart

When using line charts, stuttering and crashing occurs

Open
#1,740 1 comment 1 reaction 0 assignees View on GitHub
Line Chart Needs Reproducible Code
Dominant language
Dart
Stars
7.6k
Forks
2k
Avg merge
9d 1h
Merged PRs (30d)
2

Description

**Describe the bug**
A clear and concise description of what the bug is.

When using linear charts, it hangs or crashes.
When there is a lot of data, the simulator (iphone15 max pro) turns off
and it stutters even when there are 4 data

**To Reproduce**

//main.dart
```import 'package:flutter/material.dart';
import 'package:shared_account_app/src/views/read/folder/a.viewmodel.dart';
import 'package:provider/provider.dart';
import 'package:flutter/rendering.dart';
import 'package:intl/date_symbol_data_local.dart';

import 'src/views/read/folder/a.view.dart';

void main() {
debugPaintSizeEnabled = false;

initializeDateFormatting();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => AViewModel(),
),
],
child: const App(),
),
);
}

class App extends StatelessWidget {
const App({super.key});

@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'main',
home: MainPage(),
debugShowCheckedModeBanner: false,
);
}
}

class MainPage extends StatelessWidget {
const MainPage({super.key});

@override
Widget build(BuildContext context) {
return const _MainPageState();
}
}

class _MainPageState extends StatelessWidget {
const _MainPageState({super.key});

@override
Widget build(BuildContext context) {
return const Scaffold(
body: AView(),
);
}
}

//model.dart
class A {
final DateTime date;
final int amount;

A({
required this.date,
required this.amount,
});

factory A.fromJson(Map json) {
return A(
date: DateTime.parse(json['date']),
amount: int.parse(json['amount'].toString()),
);
}
}

//service.dart
import 'dart:convert';
import 'dart:io';

import 'a.model.dart';

class AService {
Future> getAData(DateTime startDate, DateTime endDate) async {
var file = File(
'/Users/jin0/Desktop/project2/shared_account_app/mock/annual_trend_item.mock.json');
var res = file.readAsStringSync();
var json = jsonDecode(res);

List annualTrendReport = (json['body'] as List)
.map((e) => A.fromJson(e as Map))
.toList();

return annualTrendReport;
}
}

//view.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_account_app/src/views/read/folder/a.viewmodel.dart';
import 'package:fl_chart/fl_chart.dart';

class AView extends StatefulWidget {
const AView({super.key});

@override
State createState() => _AViewState();
}

class _AViewState extends State {
DateTime startDate = DateTime.now();
DateTime endDate = DateTime.now();

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_initializeDates();
_loadInitialData();
});
}

void _initializeDates() {
final now = DateTime.now();
startDate = DateTime(now.year, now.month, 1);
endDate = DateTime(now.year, now.month + 1, 0);
}

Future _loadInitialData() async {
final aViewModel = Provider.of(context, listen: false);
aViewModel.cleanReportViewDatas();
await aViewModel.getAnnualTrendReportDatas(startDate, endDate);
}

List gradientColors = [
Colors.brown,
Colors.black,
];

bool showAvg = false;

List spots = [];
double minY = 0;
double maxY = 0;

void _updateChartData(List> annualTrendItems,
double maxAmount, double minAmount) {
print(annualTrendItems);
spots.clear();
double x = 0;
minY = minAmount.toDouble();
maxY = maxAmount.toDouble();

spots = annualTrendItems.map((e) {
FlSpot spot = FlSpot(x, (e['amount']));
x++;
return spot;
}).toList();
}

@override
Widget build(BuildContext context) {
return Consumer(
builder: (context, aViewModel, child) {
return Stack(
children: [
AspectRatio(
aspectRatio: 1.5,
child: Padding(
padding: const EdgeInsets.only(
right: 18,
left: 12,
top: 24,
bottom: 12,
),
child: LineChart(
mainData(aViewModel),
),
),
),
SizedBox(
width: 60,
height: 34,
child: TextButton(
onPressed: () {
setState(() {
showAvg = !showAvg;
});
},
child: Text(
'avg',
style: TextStyle(
fontSize: 12,
color:
showAvg ? Colors.white.withOpacity(0.5) : Colors.white,
),
),
),
),
],
);
},
);
}

LineChartData mainData(AViewModel aViewModel) {
_updateChartData(
aViewModel.aTrendItems,
aViewModel.maxAmount,
aViewModel.minAmount,
);

return LineChartData(
gridData: FlGridData(
show: true,
drawVerticalLine: true,
horizontalInterval: 1,
verticalInterval: 1,
getDrawingHorizontalLine: (value) {
return const FlLine(
color: Colors.white,
strokeWidth: 1,
);
},
getDrawingVerticalLine: (value) {
return const FlLine(
color: Colors.purple,
strokeWidth: 1,
);
},
),
titlesData: const FlTitlesData(
show: true,
rightTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
reservedSize: 30,
interval: 1,
),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
interval: 1,
reservedSize: 70,
),
),
),
borderData: FlBorderData(
show: false,
),
minX: 0,
maxX: spots.length.toDouble(),
minY: minY,
maxY: maxY,
lineBarsData: [
LineChartBarData(
spots: spots,
isCurved: true,
gradient: LinearGradient(
colors: gradientColors,
),
barWidth: 5,
isStrokeCapRound: true,
dotData: const FlDotData(
show: false,
),
belowBarData: BarAreaData(
show: false,
gradient: LinearGradient(
colors: gradientColors
.map((color) => color.withOpacity(0.1))
.toList(),
),
),
),
],
lineTouchData: LineTouchData(
enabled: false,
touchTooltipData: LineTouchTooltipData(
getTooltipColor: (spot) => Colors.white,
),
),
);
}
}

//a.viewmodel.dart
import 'package:flutter/material.dart';

import 'a.model.dart';
import 'a.service.dart';

class AViewModel extends ChangeNotifier {
final AService _aService = AService();

void cleanReportViewDatas() {
_aTrendItems.clear();
notifyListeners();
}

final List> _aTrendItems = [];

List> get aTrendItems => _aTrendItems;
double _maxAmount = 0;
double _minAmount = 0;
double get maxAmount => _maxAmount;
double get minAmount => _minAmount;

Future getAnnualTrendReportDatas(
DateTime startDate, DateTime endDate) async {
List
aTrend = await _aService.getAData(startDate, endDate);
double sumAmount = 0;
_aTrendItems.clear();
_aTrendItems.addAll(aTrend.map((e) {
double amount = sumAmount + e.amount;
sumAmount = amount;

return {
'date': e.date.toString(),
'amount': amount,
};
}));
_maxAmount = _aTrendItems.last['amount'];
_minAmount = _aTrendItems.first['amount'];

notifyListeners();
}
}

```

**Screenshots**
If applicable, add screenshots, or videoshots to help explain your problem.

**Versions**
- which version of the Flutter are you using? Flutter 3.24.1
- which version of the FlChart are you using? fl_chart: ^0.68.0

Contributor guide

Open the contributing guide

Research direction

Start by running the main.dart reproduction with Flutter 3.24.1 and fl_chart 0.68.0, then inspect the LineChart entry point in view.dart, especially mainData and _updateChartData, alongside AViewModel's data flow. Compare behavior with four points and the larger dataset shown in the report; done means the chart no longer stutters or crashes on the reported iPhone simulator.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
data-visualization, mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.