使用Flutter Riverpod等待Future解析时显示CircularProgressIndicator异常排查
问题分析与解决方案
原代码的核心问题
- 页面提前销毁:触发异步操作后立刻调用
Navigator.pop(),当前页面被直接关闭,FutureBuilder根本没机会渲染加载状态。 - 状态管理混乱:
rejectResponse是局部变量,FutureBuilder初始化时该变量未赋值,后续赋值后调用setState但页面已被弹出,完全无效。 - Riverpod与FutureBuilder搭配不当:没有利用Riverpod的状态管理能力,反而用局部变量+
FutureBuilder的方式,状态不可控且容易出错。
推荐解决方案:用StateNotifier管理异步状态(符合Riverpod最佳实践)
这种方式把异步操作的状态交给Riverpod统一管理,逻辑更清晰,状态更稳定。
第一步:创建StateNotifier处理审批状态
// 定义Provider final approveDocumentProvider = StateNotifierProvider<ApproveDocumentNotifier, AsyncValue<void>>((ref) { final repo = ref.watch(notificationRepositoryProvider); return ApproveDocumentNotifier(repo); }); // 状态管理类 class ApproveDocumentNotifier extends StateNotifier<AsyncValue<void>> { final NotificationRepository _repo; ApproveDocumentNotifier(this._repo) : super(const AsyncData(null)); Future<void> approve(int documentId) async { // 标记为加载状态 state = const AsyncLoading(); try { await _repo.approveDocument(documentId); // 操作成功,重置为无数据状态 state = const AsyncData(null); } catch (e) { // 操作失败,记录错误状态 state = AsyncError(e, StackTrace.current); } } }
第二步:在ConsumerStatefulWidget中使用
ElevatedButton( onPressed: () async { final notifier = ref.read(approveDocumentProvider.notifier); // 等待异步操作完成后再关闭页面 await notifier.approve(1); Navigator.of(context).pop(); }, child: ref.watch(approveDocumentProvider).when( data: (_) => const Text('Yes'), loading: () => const CircularProgressIndicator(), error: (_, __) => const Text('Error'), ), )
临时修复方案:调整现有代码逻辑(不推荐长期使用)
如果不想新增StateNotifier,可以修改原代码逻辑,确保页面在异步操作完成后再关闭:
// 在State类中定义Future变量 Future<void>? _approveFuture; // ... ElevatedButton( onPressed: () { setState(() { // 赋值Future并触发重绘 _approveFuture = ref.read(notificationRepositoryProvider).approveDocument(1); }); // 等待异步操作完成后再关闭页面 _approveFuture?.then((_) { Navigator.of(context).pop(); }).catchError((error) { // 可选:错误时的处理,比如留在页面显示错误 // setState(() {}); }); }, child: FutureBuilder( future: _approveFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasError) { return const Text('Error'); } return const Text('Yes'); }, ), )
内容的提问来源于stack exchange,提问作者DEPARTED
相关产品推荐
相关产品推荐

