Riverpod StateNotifier冷启动异常但热重启正常的问题求助
Riverpod StateNotifier冷启动异常但热重启正常的问题求助
各位大佬好,我现在用Riverpod做状态管理开发Flutter应用,碰到了一个很奇怪的问题:
在**冷启动(执行flutter run后第一次打开App)**时,明明网络是正常的,启动页却一直显示「无网络连接或服务器离线」的提示;但只要做一次热重启,整个流程就完全正常了——网络状态能正确识别,也会正常跳转到登录页或主应用壳。
我自己调试后怀疑是竞态条件导致的:UI在异步网络检查还没完成的时候,就用了NetworkStatus的初始状态(isNetworkOnline: false)进行渲染,而且后续网络检查完成后,状态更新没有正确触发UI刷新?或者是网络检查的逻辑在冷启动时没正确执行?
先给大家说清楚我的启动页逻辑:
启动页需要同时检查两个状态:
- 网络连接状态:不通的话直接显示错误提示
- 用户认证状态:网络通的前提下,根据认证状态跳转到对应页面
- 认证中:显示「服务器在线,检查认证中...」
- 未认证:跳登录页
- 已认证:跳主应用壳
下面是相关的代码片段:
splash_screen.dart
class SplashScreen extends ConsumerStatefulWidget { const SplashScreen({super.key}); static final String routeName = "/splashScreen"; @override ConsumerState createState() => _SplashScreenState(); } class _SplashScreenState extends ConsumerState<SplashScreen> { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(networkStatusNotifierProvider); }); } @override Widget build(BuildContext context) { final networkStatus = ref.watch(networkStatusNotifierProvider); final authState = ref.watch(authStateNotifierProvider); ref.listen<AuthState>(authStateNotifierProvider, (prev, next) { final networkStatus = ref.watch(networkStatusNotifierProvider); if (networkStatus.isNetworkOnline) { if (next.status == AuthStatus.authenticated) { if (mounted) { Navigator.pushReplacementNamed(context, MainAppShell.routeName); } } else if (next.status == AuthStatus.unauthenticated) { if (mounted) { Navigator.pushReplacementNamed(context, LoginScreen.routeName); } } } }); return Scaffold( body: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Image.asset( Constants.logoPath, height: MediaQuery.sizeOf(context).height * 0.5, width: MediaQuery.sizeOf(context).width * 0.5, ), SizedBox(height: 20), if (!networkStatus.isNetworkOnline) _buildErrorMessage("No Internet Connection or Server Offline") else if (authState.status == AuthStatus.loading || authState.status == AuthStatus.initial) _buildLoadingIndicator( "Server online. Checking authentication...", ) else if (authState.status == AuthStatus.error) _buildErrorMessage( "Authentication failed: ${authState.errorMessage ?? 'Unknown auth error'}", showLoginButton: true, ), ], ), ), ); } _buildLoadingIndicator(String message) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(message), SizedBox(height: 10), CircularProgressIndicator(), ], ), ); } _buildErrorMessage(String message, {bool showLoginButton = false}) { return Center( child: Column( children: [ Text(message), if (showLoginButton) ...[ const SizedBox(height: 10), TextButton( onPressed: () { Navigator.pushReplacementNamed(context, LoginScreen.routeName); }, child: const Text("Login"), ), ], ], ), ); } }
network_status_notifier.dart
final networkStatusNotifierProvider = StateNotifierProvider<NetworkStatusNotifier, NetworkStatus>((ref) { return NetworkStatusNotifier(ref); }); class NetworkStatusNotifier extends StateNotifier<NetworkStatus> { NetworkStatusNotifier(this._ref) : super(NetworkStatus()) { getNetworkStatus(); } final Ref _ref; void getNetworkStatus() async { state = state.copyWith(isNetworkOnline: false); final networkRepo = _ref.read(networkRepositoryProvider); final response = await networkRepo.getNetworkStatus(); if (response.isSuccess && response.data != null) { state = state.copyWith(isNetworkOnline: true); return; } else { state = state.copyWith(isNetworkOnline: false); return; } } void clearNetworkStatus() { state = state.copyWith(isNetworkOnline: false); } }
我已经尝试过的解决方法
为了修复这个问题,我试了好几种方式,但都没效果:
- 在
initState里用Future.microtask来读取network provider - 直接在
initState里调用ref.read(networkStatusNotifierProvider) - 在build方法里直接用
ref.watch监听状态(就是现在的写法) - 用
WidgetsBinding.instance.addPostFrameCallback来延迟读取provider
现在实在没思路了,想请教大家:我到底哪里考虑漏了?怎么才能确保冷启动时,网络检查完成后UI能正确更新状态,而不是一直停留在初始的「无网络」错误提示?
内容来源于stack exchange
相关产品推荐
相关产品推荐

