I am trying to build an application in which I want to show some data in a chart. I'm fetching my data from a database, and want to structure it for use in a FutureBuilder
widget and then render a line chart with multiple lines using syncfusion_flutter_charts: ^20.1.61
.
In the method where I try to structure my data in a list, so I can display multiple lines, I get the following error:
[ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: type 'Blob' is not a subtype of type 'String', stack trace: #0
I tried casting the scores[i]['name']
as a String, which didn't help. I guess I have a hard time understanding what the Blob type is and why it occurs.
Code below - and methods for database calls and fetching my data is below that. Added a comment on the line where the exception happens. Any help is greatly appreciated.
import 'database.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:syncfusion_flutter_charts/sparkcharts.dart';
class BanditData {
BanditData(this.name, this.date, this.score);
final String name;
final String date;
final int score;
}
class MyStatsPage extends StatefulWidget {
const MyStatsPage({Key? key}) : super(key: key);
@override
MyStatsPageState createState() {
return MyStatsPageState();
}
}
class MyStatsPageState extends State<MyStatsPage> {
final database = Database();
Future<List<List<BanditData>>> getBanditData() async {
var dates = await database.getDistinctDatesList();
var scores = await database.createScoreDataStruct();
var bandits = await database.getBandits();
List<List<BanditData>> banditData = [];
for (var item in bandits) {
List<BanditData> temp = [];
for (var i = 0; i < scores.length; i ) { /* <--- Exception happens on this line */
BanditData bandit =
BanditData(scores[i]['name'], dates[i], scores[i]['score'][i]);
temp.add(bandit);
}
banditData.add(temp);
}
print(banditData);
return banditData;
}
@override
Widget build(BuildContext context) {
const appTitle = "Stats";
return Scaffold(
appBar: AppBar(
title: const Text(
appTitle,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w700),
)),
body: FutureBuilder(
future: getBanditData(),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
if (snapshot.hasError) {
return ErrorWidget(Exception(
'Error occured when fetching data from database'));
} else if (!snapshot.hasData) {
return const Center(child: Text('No data found.'));
} else {
final _scores = snapshot.data![0];
final _dates = snapshot.data![1];
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: SfCartesianChart(
primaryXAxis: CategoryAxis(),
series: const <ChartSeries>[
/* Line charts here, when the data structure works */
],
))
],
);
}
}
}));
}
}
Database code:
import 'dart:async';
import 'package:intl/intl.dart';
import 'package:mysql1/mysql1.dart';
class Database {
final dateFormat = DateFormat('yyyy-MM-dd');
Future<MySqlConnection> connect() async {
var settings = ConnectionSettings(
/* REMOVED */
);
var conn = await MySqlConnection.connect(settings);
return conn;
}
Future<List<Map<String, dynamic>>> getBandits() async {
List<Map<String, dynamic>> items = <Map<String, dynamic>>[];
dynamic conn = await connect();
var results = await conn.query('select * from bandit');
for (var row in results) {
items.add({'value': row["ID"], 'label': row["bandit"]});
}
await conn.close();
return items;
}
void insertScore(id, date, course, score) async {
dynamic conn = await connect();
String query1 =
"insert into test_score (Bandit_ID, Bane, dato, Scores) values (?, ?, ?, ?)";
await conn.query(query1, [id, course, date, score]);
conn.close();
}
Future<void> updateDbActive1(id) async {
Future.delayed(const Duration(milliseconds: 500), () async {
dynamic conn = await connect();
String query = "UPDATE test_score SET IkkeAktiv = 1 WHERE Bandit_ID = ?";
await conn.query(query, [id]);
conn.close();
});
}
Future<void> updateDbActive2(id) async {
Future.delayed(const Duration(milliseconds: 500), () async {
dynamic conn = await connect();
String query =
"UPDATE test_score SET IkkeAktiv = 0 WHERE Bandit_ID = ? ORDER BY Scores DESC LIMIT 10";
await conn.query(query, [id]);
conn.close();
});
}
Future<List<String>> getDistinctDatesList() async {
List<String> dates = [];
dynamic conn = await connect();
String query =
"SELECT DISTINCT dato FROM test_score WHERE IkkeAktiv = 0 ORDER BY dato ASC";
var result = await conn.query(query);
for (var row in result) {
dates.add(dateFormat.format(row["dato"]).toString());
}
conn.close();
return dates;
}
Future<List<int>> getPlayerScoreFromDate(id) async {
dynamic conn = await connect();
var dateList = await getDistinctDatesList();
var scores = <int>[];
String query =
"SELECT * FROM test_score WHERE Bandit_ID = ? AND IkkeAktiv = 0 ORDER BY dato ASC";
var result = await conn.query(query, [id]);
var score = 0;
for (var date in dateList) {
var count = 0;
for (var row in result) {
if (date == dateFormat.format(row["dato"]).toString()) {
var value = row["Scores"];
score = value as int;
scores.add(score);
break;
} else {
count ;
if (count == result.length) {
scores.add(score);
}
continue;
}
}
}
conn.close();
return scores;
}
Future<List<Map<String, dynamic>>> createScoreDataStruct() async {
List<Map<String, dynamic>> playerScoresSum = <Map<String, dynamic>>[];
var bandits = await getBandits();
for (var bandit in bandits) {
playerScoresSum.add({
'value': bandit['value'],
'name': bandit['label'],
'scores': await getPlayerScoreFromDate(bandit['value'])
});
}
return playerScoresSum;
}
}
CodePudding user response:
Seems like it could be fixed by adding .toString()
in the method that fetches the data from the database.
Future<List<Map<String, dynamic>>> createScoreDataStruct() async {
List<Map<String, dynamic>> playerScoresSum = <Map<String, dynamic>>[];
var bandits = await getBandits();
for (var bandit in bandits) {
playerScoresSum.add({
'value': bandit['value'],
'name': bandit['label'].toString(), // <------
'scores': await getPlayerScoreFromDate(bandit['value'])
});
}
print(playerScoresSum);
return playerScoresSum;
}