Flutter Web GoRouter Chrome刷新后登录信息丢失致空值错误
问题解答
1. 单例会在Web刷新时销毁吗?
会。Web端刷新页面相当于整个Flutter应用完全重启,内存中的所有对象(包括单例)都会被销毁。你登录后存在单例里的login_info在刷新后就变成了null,仪表盘页面直接访问这个null值,就会触发「Unexpected null value」错误,关联Navigator组件大概率是因为Go Router的路由逻辑或页面渲染依赖了这个null的用户信息。
2. 是否需要用本地缓存存储登录信息?
必须要。既然内存数据在Web刷新时会丢失,就需要把登录信息持久化到本地存储中。Flutter里常用的shared_preferences包在Web端会映射到浏览器的localStorage,完全满足这个需求。
3. 如何让用户信息在应用内持续可访问?
结合本地缓存持久化和状态管理来解决,具体步骤如下:
步骤1:登录成功后持久化用户信息
登录接口返回login_info后,除了更新内存中的单例/状态,还要把信息序列化后存到本地缓存:
import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert'; // 登录成功后的处理 void handleLoginSuccess(LoginInfo loginInfo) async { // 更新单例 UserSingleton.instance.loginInfo = loginInfo; // 持久化到本地缓存 final prefs = await SharedPreferences.getInstance(); await prefs.setString('login_info', jsonEncode(loginInfo.toJson())); }
步骤2:应用启动时恢复用户信息
在main函数初始化时,先从本地缓存读取并恢复用户信息,保证应用启动后内存中已有数据:
void main() async { // 必须先初始化Flutter绑定 WidgetsFlutterBinding.ensureInitialized(); final prefs = await SharedPreferences.getInstance(); final loginInfoJson = prefs.getString('login_info'); if (loginInfoJson != null) { // 反序列化恢复用户信息 final loginInfo = LoginInfo.fromJson(jsonDecode(loginInfoJson)); UserSingleton.instance.loginInfo = loginInfo; } runApp(const MyApp()); }
步骤3:优化路由逻辑避免null引用
修改Go Router的redirect逻辑,优先检查本地缓存或初始化后的单例状态,避免刷新后因为null值导致路由错误:
final router = GoRouter( redirect: (context, state) { final hasLoginInfo = UserSingleton.instance.loginInfo != null; final isOnLoginPage = state.location == '/login'; // 未登录且不在登录页,跳转到登录页 if (!hasLoginInfo && !isOnLoginPage) { return '/login'; } // 已登录且在登录页,跳转到仪表盘 if (hasLoginInfo && isOnLoginPage) { return '/dashboard'; } // 其他情况正常跳转 return null; }, routes: [ GoRoute(path: '/login', builder: (context, state) => const LoginPage()), GoRoute(path: '/dashboard', builder: (context, state) => const DashboardPage()), ], );
额外注意事项
- 不要在组件的
build方法中直接访问单例的login_info,建议用状态管理(比如Provider、Riverpod)包裹用户信息,组件通过监听状态来获取数据,避免null引用异常。 - 要处理token过期的情况:本地缓存的用户信息可能过期,在发起API请求时要验证token有效性,过期则清除本地缓存并跳转到登录页。
- 序列化/反序列化要确保正确:
LoginInfo类需要实现toJson和fromJson方法,避免解析错误导致数据恢复失败。
内容的提问来源于stack exchange,提问作者hemant
相关产品推荐
相关产品推荐

