Flutter Riverpod中FutureProvider与StateNotifier的作用域设计问题
Riverpod作用域FutureProvider优化方案
问题1:消除冗余null值处理
通过调整meProvider的逻辑,让它仅在用户处于登录状态时执行Profile请求,直接返回非nullable的Profile类型,彻底避免Widget层的null值处理。
优化AuthNotifier判断逻辑
class AuthNotifier extends StateNotifier<AuthState> { // 修正类名大写规范 final Ref ref; late API _api; AuthNotifier(this.ref) : super(const AuthStateLoggedOut()) { _api = ref.read(APIProvider.notifier); } Future<bool> login(String email, String password) async { state = const AuthStateLoading(); try { await _api.login(email, password); } on AuthWrongCredentialsException catch (error) { state = AuthStateError(error.msg); return false; } state = const AuthStateLoggedIn(); return true; } API api() { return _api; } bool isLoggedIn() { return state is AuthStateLoggedIn; // 改用类型判断,更可靠 } } final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) { return AuthNotifier(ref); });
修改后的meProvider
final meProvider = FutureProvider<Profile>((ref) async { // 等待用户进入登录状态,未登录时Future保持pending(loading状态) await ref.waitUntil(() => ref.watch(authProvider) is AuthStateLoggedIn); final auth = ref.read(authProvider.notifier); return await auth.api().getOwnProfile(); });
简化后的Widget代码
@override Widget build(BuildContext context, WidgetRef ref) { final meAsync = ref.watch(meProvider); return meAsync.when( loading: () => const Spinner(), data: (profile) => buildProfileWidget(profile), // 无需处理null error: (error, stackTrace) => Text(error.toString()), ); }
问题2:仅在auth特定状态(loggedIn)触发watch
使用Riverpod的select方法,精准监听AuthState是否为AuthStateLoggedIn,只有当状态切换到登录状态时,才会触发meProvider的重建:
final meProvider = FutureProvider<Profile>((ref) async { // 仅监听"是否登录"的状态变化,其他状态(loading/error/loggedOut)不会触发重建 ref.watch(authProvider.select((state) => state is AuthStateLoggedIn)); final auth = ref.read(authProvider.notifier); return await auth.api().getOwnProfile(); });
结合ref.waitUntil可进一步确保只有登录状态下才执行API请求。
问题3:强制FutureProvider保持loading直到满足条件
利用ref.waitUntil方法,让FutureProvider的异步任务暂停,直到用户进入登录状态,此时FutureProvider会一直处于loading状态,直到条件满足后才执行API请求并切换到data状态:
await ref.waitUntil(() => ref.watch(authProvider) is AuthStateLoggedIn);
这段代码会阻塞Future的执行,直到传入的条件返回true,完美实现"等待满足条件再执行"的需求。
内容的提问来源于stack exchange,提问作者DerCommodore
相关产品推荐
相关产品推荐

