Reputation: 47
I'm trying to build an app in flutter with a chart that updates every 30 seconds with the latest data from a website. The chart is displayed correctly at first but when the new data is added to chart without replacing the previous one so that with time more and more lines are shown. I've tried many ways but I always get the same result. In the code I'm using fl_animated_linechart but I got the same result with charts_flutter. Can you please help me?
Code in main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'dart:convert';
import 'dart:async';
import 'chart.dart';
import 'package:fl_animated_linechart/fl_animated_linechart.dart';
final Map<DateTime, double> dataSet = {};
final Map<DateTime, double> dataRec = {};
void main() => runApp(MaterialApp(
home: Home(),
));
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
ChartWidget chartWidget;
double set_temp = 18.0;
double rec_temp = 15.0;
String get_url = 'url';
String post_url = 'url';
@override
void initState() {
super.initState();
fetchData();
Timer.periodic(new Duration(seconds: 30), (time) async {
fetchData();
});
}
void fetchData() async{
Response response = await get(get_url);
List data = jsonDecode(response.body);
print(response.body);
setState(() {
set_temp = double.parse(data[9]['setTemperature']);
rec_temp = double.parse(data[9]['recTemperature']);
for(int i=0; i < 10; i++){
dataSet[DateTime.parse(data[i]['date'])] = double.parse(data[i]['setTemperature']);
dataRec[DateTime.parse(data[i]['date'])] = double.parse(data[i]['recTemperature']);
}
});
}
void sendData() async{
Response response = await post(post_url, body: {'tempSet': set_temp.toString()});
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'TERMOSMART'
),
backgroundColor: Colors.amber,
centerTitle: true,
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(
height: 40.0,
),
Padding(
padding: const EdgeInsets.all(32.0),
child: SizedBox(
height: 200.0,
child: chartWidget,
),
),
],
)
)
);
}
}
class ChartWidget extends StatefulWidget {
@override
_ChartWidgetState createState() => _ChartWidgetState();
}
class _ChartWidgetState extends State<ChartWidget> {
@override
Widget build(BuildContext context) {
return Chart(dataSet: dataSet, dataRec: dataRec);
}
}
Code in chart.dart
import 'package:flutter/material.dart';
import 'package:fl_animated_linechart/fl_animated_linechart.dart';
class Chart extends StatefulWidget {
Map<DateTime, double> dataRec = {};
Map<DateTime, double> dataSet = {};
Chart({this.dataRec, this.dataSet});
@override
_ChartState createState() => _ChartState();
}
class _ChartState extends State<Chart> {
@override
Widget build(BuildContext context) {
LineChart chart;
chart = LineChart.fromDateTimeMaps(
[widget.dataRec, widget.dataSet],
[Colors.green, Colors.blue],
['C', 'C']);
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedLineChart(
chart,
key: UniqueKey(),
), //Unique key to force animations
)
);
}
}
Upvotes: 1
Views: 1464
Reputation: 54377
You can copy paste run full code below
I use random number to simulate this case
You can use dataSet.clear();
and dataRec.clear();
to remove old data;
setState(() {
dataSet.clear();
dataRec.clear();
for (int i = 0; i < 10; i++) {
var now = DateTime.now();
print(i);
Random random = new Random();
int randomNumber1 = random.nextInt(100);
int randomNumber2 = random.nextInt(100);
dataSet[now.add(Duration(days: i))] = randomNumber1.toDouble();
dataRec[now.add(Duration(days: i))] = randomNumber2.toDouble();
}
});
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'dart:convert';
import 'dart:async';
import 'package:fl_animated_linechart/fl_animated_linechart.dart';
import 'dart:math';
final Map<DateTime, double> dataSet = {};
final Map<DateTime, double> dataRec = {};
void main() => runApp(MaterialApp(
home: Home(),
));
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
ChartWidget chartWidget;
double set_temp = 18.0;
double rec_temp = 15.0;
String get_url = 'url';
String post_url = 'url';
@override
void initState() {
super.initState();
/* WidgetsBinding.instance.addPostFrameCallback((_){
fetchData();
});*/
fetchData();
Timer.periodic(new Duration(seconds: 3), (time) async {
fetchData();
});
}
void fetchData() async {
/*Response response = await get(get_url);
List data = jsonDecode(response.body);
print(response.body);*/
setState(() {
/*set_temp = double.parse(data[9]['setTemperature']);
rec_temp = double.parse(data[9]['recTemperature']);*/
dataSet.clear();
dataRec.clear();
for (int i = 0; i < 10; i++) {
var now = DateTime.now();
print(i);
Random random = new Random();
int randomNumber1 = random.nextInt(100);
int randomNumber2 = random.nextInt(100);
dataSet[now.add(Duration(days: i))] = randomNumber1.toDouble();
dataRec[now.add(Duration(days: i))] = randomNumber2.toDouble();
}
});
}
/*void sendData() async {
Response response =
await post(post_url, body: {'tempSet': set_temp.toString()});
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
}
*/
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TERMOSMART'),
backgroundColor: Colors.amber,
centerTitle: true,
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(
height: 40.0,
),
Padding(
padding: const EdgeInsets.all(32.0),
child: SizedBox(
height: 200.0,
child: ChartWidget(),
),
),
],
)));
}
}
class ChartWidget extends StatefulWidget {
@override
_ChartWidgetState createState() => _ChartWidgetState();
}
class _ChartWidgetState extends State<ChartWidget> {
@override
Widget build(BuildContext context) {
return Chart(dataSet: dataSet, dataRec: dataRec);
}
}
class Chart extends StatefulWidget {
Map<DateTime, double> dataRec = {};
Map<DateTime, double> dataSet = {};
Chart({this.dataRec, this.dataSet});
@override
_ChartState createState() => _ChartState();
}
class _ChartState extends State<Chart> {
@override
Widget build(BuildContext context) {
LineChart chart;
chart = LineChart.fromDateTimeMaps([dataRec, dataSet],
[Colors.green, Colors.blue], ['C', 'C']);
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedLineChart(
chart,
key: UniqueKey(),
), //Unique key to force animations
));
}
}
Upvotes: 1