Riverpod状态变更方法未按预期更新状态问题排查
问题排查与修复方案
1. 数据库日期匹配问题(核心原因)
问题点
- 插入数据时日期赋值错误:
insertSet方法里误用了比较运算符==而非赋值运算符=,导致插入的date字段未被设置为yyyy-MM-dd格式字符串,而是使用数据库默认的CURRENT_TIMESTAMP(格式为yyyy-MM-dd HH:mm:ss)。 - 查询条件不匹配:
getTodayItems方法用yyyy-MM-dd格式字符串匹配带时间戳的date字段,自然查不到数据,最终状态变为空列表。
修复代码
修改SQLHelper的insertSet方法:
static Future<int> insertSet(Set set) async { final db = await SQLHelper.db(); DateTime now = DateTime.now(); String formattedDate = DateFormat('yyyy-MM-dd').format(now); // 修正为赋值运算符 set.date = formattedDate; final id = await db.insert('sets', set.toJson(), conflictAlgorithm: sql.ConflictAlgorithm.replace); return id; }
若需保留时间戳信息,可修改查询语句匹配日期部分:
static Future<List<Map<String, dynamic>>> getTodayItems() async { final db = await SQLHelper.db(); DateTime now = DateTime.now(); String formattedDate = DateFormat('yyyy-MM-dd').format(now); // 使用LIKE匹配日期前缀 final results = await db.rawQuery( 'SELECT * FROM sets WHERE date LIKE ?', ['$formattedDate%'] ); print(results); return results; }
2. getTodayItems方法缺少await
原方法调用db.rawQuery时未加await,导致返回未完成的Future,无法获取实际查询结果。修复后加上await:
static Future<List<Map<String, dynamic>>> getTodayItems() async { final db = await SQLHelper.db(); DateTime now = DateTime.now(); String formattedDate = DateFormat('yyyy-MM-dd').format(now); // 加上await获取实际查询结果 final results = await db.rawQuery( 'SELECT * FROM sets WHERE date = ?', [formattedDate] ); print(results); return results; }
3. ListView构建时的错误调用
在ListView.builder的itemBuilder中调用getTodaySets()会导致每个item构建时都触发查询,造成无限刷新和性能浪费,且状态更新时机混乱。
修复方案
将getTodaySets()移到页面初始化时调用,例如在HookWidget中使用useEffect:
// 页面初始化时加载今日数据 useEffect(() { ref.read(setsProviderProvider.notifier).getTodaySets(); return null; }, []); // ListView仅负责渲染 child: ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: ref.watch(setsProviderProvider).length, itemBuilder: ((_, index) { 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()), ], ), ); }), ),
4. 额外建议:状态初始化自动加载数据
可在SetsProvider的build方法中自动加载数据,避免手动调用时机问题:
@riverpod class SetsProvider extends _$SetsProvider { @override List<Set> build() { // 初始化时自动加载今日数据 getTodaySets(); return []; } // 其他方法不变 }
内容的提问来源于stack exchange,提问作者JOHN436456
相关产品推荐
相关产品推荐

