Flutter使用Provider实现MaterialApp.router响应式时热重载白屏问题
问题根因分析
- StreamProvider每次构建都会创建新的
AuthService实例,热重载时旧的用户状态流被丢弃,新流和原有路由状态不匹配,导致路由栈崩溃白屏 - 若
_appRouter在App组件的build方法中初始化,每次组件重建都会生成新的路由实例,声明式路由的状态无法在新旧实例间同步,直接触发白屏问题 - 无状态保留的路由代理重建逻辑,导致热重载时路由栈状态丢失
修复方案
1. 改造AuthService为单例,避免重复创建实例
class AuthService { // 单例实现逻辑 static final AuthService _instance = AuthService._internal(); factory AuthService() => _instance; AuthService._internal(); // 原有业务逻辑保留不变 Stream<User?> get user => // 你的用户流实现 User? get currentUser => // 你的当前用户获取逻辑 }
改造后你原有的根Provider代码无需修改,所有AuthService()调用都会拿到同一个实例,不会出现流反复替换的问题。
2. 固定路由实例,添加热重载兼容参数
将_appRouter的初始化从build方法中移出,仅在组件初始化时创建一次,同时给AutoRouterDelegate添加热重载状态同步参数:
// 建议将App改为StatefulWidget class App extends StatefulWidget { const App({super.key}); @override State<App> createState() => _AppState(); } class _AppState extends State<App> { // 路由实例仅初始化一次,热重载不会重建 final _appRouter = AppRouter(); @override Widget build(BuildContext context) { final user = Provider.of<User?>(context); return MaterialApp.router( routerDelegate: AutoRouterDelegate.declarative( _appRouter, // 开启热重载时路由栈主动重建,同步最新状态 rebuildStackOnHotReload: true, routes: (_) => [ if (user != null) const HomeRoute() else const LoginRoute(), ], ), routeInformationParser: _appRouter.defaultRouteParser( includePrefixMatches: true, ), // 其他配置保留不变 ); } }
3. 可选优化:减少不必要的组件重建
使用Selector替代直接Provider.of监听,仅当用户状态真实发生变化时才触发组件重建,降低热重载异常概率:
将build方法中的用户状态获取逻辑替换为:
final user = context.select<User?, User?>((currentUser) => currentUser);
内容的提问来源于stack exchange,提问作者Henry Li
相关产品推荐
相关产品推荐

