I’m new to Flutter and facing some difficulties.
I’m building an expense tracking app and trying to implement a database using the sqflite package. However, whenever I attempt to add a new transaction, I get the exception ‘This will throw an exception in the future. For now it is displayed once per type’ in the debug console, and the app freezes. Am I misusing a callback function?
The Relevant code follows:
Here is my DB definition and operations code:
class DbUtil {
DbUtil._();
static final DbUtil instance = DbUtil._();
static Database? _database;
get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
}
_initDatabase() async {
return await sql.openDatabase(
path.join(await sql.getDatabasesPath(), 'transactions.db'),
version: 1,
onCreate: _onCreate,
);
}
_onCreate(Database db, int version) async {
await db.execute(
'CREATE TABLE transactions (id TEXT PRIMARY KEY, title TEXT, value FLOAT, date DATE ,category TEXT)');
}
Future<void> insert(String table, Map<String, Object> data) async {
final db = await database;
await db.insert(table, data,
conflictAlgorithm: sql.ConflictAlgorithm.replace);
}
}
Next, my main.dart (I removed some code to keep it concise on what is relevant):
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Expenses',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Category>? category;
final _baseUrl = 'https://expenses-a210d-default-rtdb.firebaseio.com/';
List<Transact> _transactions = [];
_openTransactionFormModal(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (_) {
return TransactionForm(_addTransaction);
},
);
}
_addTransaction(String title, double value, DateTime date, String category) {
final newTransaction = Transact(
id: Random().nextDouble().toString(),
title: title,
value: value,
date: date,
category: category,
);
setState(() {
_transactions.add(newTransaction);
_sumTotalCategory(newTransaction);
_addToDb(newTransaction);
});
Navigator.of(context).pop();
}
_addToDb(transaction) async {
await DbUtil.instance.insert(
'transactions',
{
'id': transaction.id,
'title': transaction.title,
'value': transaction.value,
'date': transaction.date,
'category': transaction.category,
},
);
}
@override
Widget build(BuildContext context) {
final appBar = AppBar(
title: Text(
'Despesas Pessoais',
style: TextStyle(
fontSize: 20 * MediaQuery.of(context).textScaleFactor,
),
),
actions: [
// IconButton(
// onPressed: () => loadTransactions(),
// icon: Icon(Icons.refresh),
// ),
IconButton(
onPressed: () => _openTransactionFormModal(context),
icon: Icon(Icons.add),
),
]);
final availableHeight = MediaQuery.of(context).size.height -
appBar.preferredSize.height -
MediaQuery.of(context).padding.top;
return Scaffold(
appBar: appBar,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
PieChartExpenses(valueSum),
Container(
width: double.infinity,
child: Card(
color: Color.fromARGB(255, 2, 84, 90),
elevation: 5,
child: total_sum(valueSum: valueSum),
),
),
Container(
height: availableHeight * 0.7,
child: Column(
children: [
TransactionList(_transactions, _removeTransaction),
],
),
),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _openTransactionFormModal(context),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
I attempted to modify the insert function based on the solution from this answer, but it didn’t work.
I also tried modifying the function to close the database afterward, but that had no effect either. From what I can tell, the database isn’t even being opened.
After the App freezes, I tried to restart it. The following messages came on the Debug Console:
E/flutter (11237): #24 DbUtil.insert db_util.dart:35
E/flutter (11237): <asynchronous suspension>
E/flutter (11237): #25 _MyHomePageState._addToDb main.dart:109
E/flutter (11237): <asynchronous suspension>
The line 109 on the main.dart is the one containing “transactions”, (third line on the _addToDB function).
The line 35 in db_util.dart is the one that reads await db.insert(table, data, on the insert function.
8