使用Riverpod的StateNotifier调用when方法遇空安全及类型错误
问题:Riverpod StateNotifier调用when方法报错处理
尝试使用Riverpod的StateNotifier实现认证功能时,调用when方法遇到以下报错:
- 初始报错:
The method 'when' can't be unconditionally invoked because the receiver can be 'null' - 添加
!强制非空后报错:The method 'when' isn't defined for the type 'Object'
相关代码
MainPage代码
class MainPage extends ConsumerWidget { const MainPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(emailPasswordSignInControllerProvider); return state.when( data: (state) { return state == AuthState.authenticated ? const SharedLayout() : const LoginScreen(); }, error: (error, stackTrace) => const Scaffold( body: Center(child: Text("Error")), ), loading: () => const Scaffold( body: Center( child: CircularProgressIndicator(), ), ), ); }
控制器代码
class EmailPasswordSignInController extends StateNotifier<AsyncValue<AuthState>> { EmailPasswordSignInController({required this.authRepository}) : super(const AsyncValue.data(AuthState.notAuthenticated)); final AuthRepository authRepository; Future<void> submit(String email, String password) async { try { state = const AsyncValue.loading(); await authRepository.signInWithEmailAndPassword(email, password); state = const AsyncValue.data(AuthState.authenticated); } catch (e, st) { state = AsyncValue.error(e, st); } } } final emailPasswordSignInControllerProvider = StateNotifierProvider((ref) { final authRepository = ref.watch(authRepositoryProvider); return EmailPasswordSignInController(authRepository: authRepository); });
仓库代码
class AuthRepository { Future<String> signInWithEmailAndPassword( String email, String password, ) async { try { final String token; final Map<String, dynamic> jsonData; final url = Uri.parse('http://192.168.1.9:5000/api/v1/auth/login'); final response = await http.post(url, body: jsonEncode({ "email": email, "password": password, }), headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }); jsonData = jsonDecode(response.body); if (response.statusCode == 200) { token = jsonData['token']; return token; } return "error"; } on Exception catch (e) { print(e.toString()); return e.toString(); } } } final authRepositoryProvider = Provider<AuthRepository>((ref) { return AuthRepository(); });
解决方案
问题根源是StateNotifierProvider未指定泛型参数,默认会推断为StateNotifierProvider<Object, Object>,导致ref.watch返回Object类型,既没有when方法,也会触发空安全报错。
修复步骤:
- 给
emailPasswordSignInControllerProvider添加完整泛型约束,明确StateNotifier子类和状态类型:
final emailPasswordSignInControllerProvider = StateNotifierProvider<EmailPasswordSignInController, AsyncValue<AuthState>>((ref) { final authRepository = ref.watch(authRepositoryProvider); return EmailPasswordSignInController(authRepository: authRepository); });
- 修改后,MainPage中
ref.watch会正确返回AsyncValue<AuthState>类型,直接调用when方法即可,无需添加!强制非空。
内容的提问来源于stack exchange,提问作者Mohammed M
相关产品推荐
相关产品推荐

