So I have a state in riverpod which holds a List of sets then I have two methods that make it a List of all the sets in the database and another that makes the state only today sets as follows:
u/riverpod
class SetsProvider extends _$SetsProvider {
u/override
List<Set> build() {
return [];
}
void refresh() async {
final data = await SQLHelper.getAllSets();
state = data.map((e) => Set.fromJson(e)).toList();
}
void getTodaySets() async {
final data = await SQLHelper.getTodayItems();
state = data.map((e) => Set.fromJson(e)).toList();
}
When I call
final list = ref.watch(setsProviderProvider);
it works perfectly
But when I try to change the state to return only todays items it just doesn't work:
ref.read(setsProviderProvider.notifier).getTodaySets();
it just makes my list empty when I watch the setProvider after that. What could I be doing wrong?
here is my dbhelper class:
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart' as sql;
import 'set_model.dart';
import 'package:intl/intl.dart';
class SQLHelper {
//method to create table
static Future<void> createTables(sql.Database database) async {
await database.execute("""CREATE TABLE sets(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
exerciseName TEXT,
totalWeight TEXT,
totalReps TEXT,
date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
isFavorited INTEGER
)
""");
print('Database created');
}
//method to open the database called db
static Future<sql.Database> db() async {
return sql.openDatabase('dbsets.db', version: 1,
onCreate: (sql.Database database, int version) async {
await createTables(database); //calling that create table method above
});
}
static Future<int> insertSet(Set set) async {
final db = await SQLHelper.db(); //opening the database
DateTime now = DateTime.now();
String formattedDate = DateFormat('yyyy-MM-dd').format(now);
//Changing the Date to now meaning ill make the date not required in a Set object
set.date == formattedDate;
final id = await db.insert('sets', set.toJson(), //toJson calls the map
conflictAlgorithm: sql.ConflictAlgorithm.replace);
return id;
}
static Future<List<Map<String, dynamic>>> getAllSets() async {
final db = await SQLHelper.db();
return db.query('sets', orderBy: 'id');
}
static Future<List<Map<String, dynamic>>> getTodayItems() async {
final db = await SQLHelper.db(); //get connection
DateTime now = DateTime.now();
String formattedDate = DateFormat('yyyy-MM-dd').format(now);
final results =
db.rawQuery('SELECT * FROM sets WHERE date = ?', [formattedDate]);
print(results.toString());
return results;
}
}
And where I am trying to show the sets in Main.dart:
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: ref.watch(setsProviderProvider).length,
itemBuilder: ((_, index) {
ref.read(setsProviderProvider.notifier).getTodaySets();
final list = ref.watch(setsProviderProvider);
var set = list[index];
return ListTile(
title: Text(set.exerciseName.toString()),
subtitle: Column(
children: [
Text(
set.totalWeight.toString(),
),
Text(
set.totalReps.toString(),
)
],
),
);
}),
),
First don't put database calls in during build
, it might run multiple time.
You could put it in places such as initState
or main()
.
The list didn't update because the initial list is empty, itemCount
is 0, so item builder of ListView
is never called.
Update: I meant Widget.build
, not provider build
. The best practice is to call it in provider's build, but this would also change the provider to async provider.
itemBuilder: ((_, index) {
ref.read(setsProviderProvider.notifier).getTodaySets(); // <- This shouldn't be here/
final list = ref.watch(setsProviderProvider);