如何在同步Riverpod Provider中传递异常并捕获?
问题原因
你无法直接捕获UserNotSignedInException的核心原因是:Riverpod会将同步Provider抛出的异常自动包装为ProviderException,你的catch块只监听原始异常类型,自然无法命中。
解决方案
方案1:捕获ProviderException并检查内部异常类型
直接修改捕获逻辑,先捕获Riverpod的包装异常,再判断内部的真实异常类型:
try { ref.read(currentUserProvider); resolver.next(); } on ProviderException catch (e) { if (e.exception is UserNotSignedInException) { logger('User is not logged in, pushing intro route'); router.push(const IntroRoute()); } else { // 重新抛出非目标类型的异常,避免吞掉其他错误 rethrow; } }
方案2:避免在Provider内抛出异常(更推荐)
同步Provider抛出异常会让其进入错误状态,后续每次读取都需要处理异常逻辑,不如直接返回明确的状态值,代码更直观:
方式A:返回可选类型User?
修改Provider:
@Riverpod(dependencies: [firebaseAuth]) User? currentUser(CurrentUserRef ref) { return ref.watch(firebaseAuthProvider).currentUser; }
读取时直接判断:
final user = ref.read(currentUserProvider); if (user == null) { logger('User is not logged in, pushing intro route'); router.push(const IntroRoute()); } else { resolver.next(); }
方式B:用密封类定义明确状态(可读性更强)
先定义状态密封类:
sealed class CurrentUserState {} class LoggedIn extends CurrentUserState { final User user; LoggedIn(this.user); } class NotLoggedIn extends CurrentUserState {}
修改Provider返回状态类:
@Riverpod(dependencies: [firebaseAuth]) CurrentUserState currentUserState(CurrentUserStateRef ref) { final user = ref.watch(firebaseAuthProvider).currentUser; return user != null ? LoggedIn(user) : NotLoggedIn(); }
读取时通过switch处理不同状态:
switch (ref.read(currentUserStateProvider)) { case LoggedIn(:final user): resolver.next(); case NotLoggedIn(): logger('User is not logged in, pushing intro route'); router.push(const IntroRoute()); }
内容的提问来源于stack exchange,提问作者Dario Digregorio
相关产品推荐
相关产品推荐

