使用FutureProvider和when()方法时CircularProgressIndicator不显示的问题
问题描述
希望通过FutureProvider和when()方法在加载过程中显示CircularProgressIndicator(),目前代码中print("It works");能正常执行,但loading位置的加载指示器从未显示,是否错误使用了方法,还是需要调整其他内容?
原代码
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:cards/view/register2.dart'; import 'package:cards/view/register4.dart'; import 'package:cards/main.dart'; import 'gender.dart'; import 'header.dart'; import 'navigate.dart'; import 'style.dart'; final authFutureProvider = FutureProvider<bool>( (ref) async => authUser(ref), ); class Register3Widget extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final authC = ref.watch(authFutureProvider); Widget? loading; authC.when( data: (data) {}, error: (error, stackTrace) {}, loading: () { print("It works");//测试代码,确实能执行 final loading = CircularProgressIndicator(); }, ); final alertMessage = ref.watch(completeErrorMessage); return Scaffold( body: Padding( padding: const EdgeInsetsDirectional.fromSTEB(20, 75, 20, 0), child: Column( children: [ Container( width: double.infinity, height: 50, alignment: Alignment.topLeft, child: Image.asset('images/logo.png'), ), Container( padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0), margin: const EdgeInsets.only(top: 30), width: double.infinity, child: Column( children: [ Align( child: GenderSelect(), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Align( alignment: Alignment.topRight, child: MyNavigator( destinationTo: Register2Widget(), context: context, goBack: "back", ), ), Align( child: MyNavigator( destinationTo: Register4Widget(), context: context, goBack: "Send Email"), ), ]), Align( child: loading,//这里应该显示加载指示器 ), Container( alignment: Alignment.centerLeft, child: alertMessage, ), ], ), ), ], ), )); } }
额外尝试代码
尝试1
authC.when( data: (data) {}, error: (error, stackTrace) {}, loading: () { final loading = WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( context: context, builder: (context) { return const Center( child: CircularProgressIndicator(), ); } ); }); }, );
尝试2
loading: () { final loading = WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( context: context, builder: (context) { return const Center( child: CircularProgressIndicator(), ); } ); Navigator.of(context).pop(); }); },
问题原因及解决方案
核心错误
- 局部变量遮蔽:在
loading回调里声明的final loading = CircularProgressIndicator();是局部变量,和外部的Widget? loading;没有关联,外部变量始终为null,因此不会显示任何内容。 - 错误使用
when()方法:when()的设计初衷是返回对应状态的Widget,而非单纯执行回调逻辑。由于ConsumerWidget的build方法会在Provider状态变化时重新执行,正确做法是用when()直接生成UI,而非给外部变量赋值。
正确实现方式
直接在需要显示加载状态的位置使用authC.when(),根据不同状态返回对应Widget:
class Register3Widget extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final authC = ref.watch(authFutureProvider); final alertMessage = ref.watch(completeErrorMessage); return Scaffold( body: Padding( padding: const EdgeInsetsDirectional.fromSTEB(20, 75, 20, 0), child: Column( children: [ Container( width: double.infinity, height: 50, alignment: Alignment.topLeft, child: Image.asset('images/logo.png'), ), Container( padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0), margin: const EdgeInsets.only(top: 30), width: double.infinity, child: Column( children: [ Align(child: GenderSelect()), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Align( alignment: Alignment.topRight, child: MyNavigator( destinationTo: Register2Widget(), context: context, goBack: "back", ), ), Align( child: MyNavigator( destinationTo: Register4Widget(), context: context, goBack: "Send Email"), ), ]), // 直接用when处理状态 authC.when( data: (data) => const SizedBox.shrink(), // 加载完成显示空组件 error: (error, stackTrace) => Text('加载失败: $error'), // 错误状态显示提示 loading: () => const CircularProgressIndicator(), // 加载中显示指示器 ), Container( alignment: Alignment.centerLeft, child: alertMessage, ), ], ), ), ], ), )); } }
对额外尝试的点评
- 尝试1:用
showDialog弹出加载框,但未在data或error状态时关闭对话框,会导致加载完成后对话框一直停留,无法交互。 - 尝试2:在
addPostFrameCallback里立刻调用Navigator.pop(),此时对话框还未完成显示就被关闭,因此看不到加载指示器,逻辑完全错误。
内容的提问来源于stack exchange,提问作者SugiuraY
相关产品推荐
相关产品推荐

