You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:35:55