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(),
)
],
),
);
}),
),
2
Answers
First don’t put database calls in during
build
, it might run multiple time.You could put it in places such as
initState
ormain()
.The list didn’t update because the initial list is empty,
itemCount
is 0, so item builder ofListView
is never called.You should have the filter provider watch the full-list provider, as well as take a filter argument as a family key. Then, as you update the full-list provider (either from local mutations, or from watching a database stream), the filter provider(s) will have the proper value, caching as long as they are being watched.