Flutter Riverpod StateNotifier状态未更新,求助排查原因
问题:StateNotifier状态更新后UI无响应(Riverpod 1.0.4)
在Riverpod 1.0.4版本中使用自定义状态类结合StateNotifier时,执行StateNotifier内的函数后,函数内部打印显示状态已变更,但UI始终停留在ListInit状态,无任何更新。此前在Riverpod 0.14.0+3版本中相同代码结构可正常运行,已尝试适配1.0.x版本改动,无报错但问题依旧。
状态类与StateNotifier实现
import 'package:finanz_app/models/konten.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hive_flutter/hive_flutter.dart'; abstract class ListState { const ListState(); } class ListInit extends ListState { const ListInit(); } class ListLoding extends ListState { const ListLoding(); } class ListLoded extends ListState { final List<Konten> konten; const ListLoded(this.konten); } class ListError extends ListState { final String errorMessage; const ListError(this.errorMessage); } final listNotifierProvider = StateNotifierProvider((ref) { return ListStateNotifier(); }); class ListStateNotifier extends StateNotifier<ListState> { ListStateNotifier() : super(const ListInit()); Future<void> getFromDB() async { state = const ListLoding(); final box = Hive.box('konten'); final List<Konten> kontenData = box.keys.map((key) { final Konten value = box.get(key); return value; }).toList(); print(kontenData.length); state = ListLoded(kontenData); print(state.runtimeType); } Future<void> add(Konten konto) async { final box = Hive.box('konten'); box.add(konto); print(state.runtimeType); getFromDB(); } Future<void> deletedAll() async { final box = Hive.box('konten'); for (int key in box.keys) { box.delete(key); } getFromDB(); } }
UI层Consumer代码
... body: Consumer( builder: (context, ref, child) { final state = ref.watch(listNotifierProvider); print(state.runtimeType); if (state is ListInit) { return const Text( "InitState", ); } else if (state is ListLoding) { return const CircularProgressIndicator(); } else if (state is ListLoded) { return Text(state.konten.length.toString()); } else if (state is ListError) { return Text("ERROR: ${state.errorMessage}"); } else { return const Text("Unknown ERROR"); } }, ), ...
ProviderScope配置
@override Widget build(BuildContext context) { return ProviderScope( child: MaterialApp( ... initialRoute: '/', routes: { "/": (context) => const HomePage(), }, ), ); }
解决方案
1. 修复StateNotifierProvider的泛型声明
Riverpod 1.0+版本对StateNotifierProvider的类型推断做了严格限制,必须显式指定泛型参数<StateNotifierType, StateType>,否则UI无法正确监听状态变化。
修改后的Provider定义:
final listNotifierProvider = StateNotifierProvider<ListStateNotifier, ListState>((ref) { return ListStateNotifier(); });
2. 确保初始化时调用状态加载方法
检查UI页面是否在初始化时调用了getFromDB方法,比如在initState中:
@override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(listNotifierProvider.notifier).getFromDB(); }); }
如果没有调用该方法,状态会一直停留在ListInit,自然不会触发UI更新。
3. 检查Hive初始化是否完成
确保在使用Hive之前已经完成初始化,比如在main函数中:
void main() async { await Hive.initFlutter(); Hive.registerAdapter(KontenAdapter()); // 确保注册了Konten的适配器 await Hive.openBox('konten'); runApp(const MyApp()); }
内容的提问来源于stack exchange,提问作者Berkkan
相关产品推荐
相关产品推荐

