Flutter登录后存储Token、Go Router跳转及JSON数据处理求助
解决方案
一、修复JSON解析错误
你的Loginuser.fromJson直接将json['userinfo']赋值给userinfo是错误的,必须通过Userinfo.fromJson解析嵌套对象;另外Userinfo的字段类型明显不符合实际数据(name应为字符串,branchcode/role大概率是整数),先修正数据模型:
class Userinfo { final int branchcode; final int role; final String name; Userinfo({required this.branchcode, required this.role, required this.name}); factory Userinfo.fromJson(Map<String, dynamic> json) { return Userinfo( branchcode: json['branchcode'] as int, role: json['role'] as int, name: json['name'] as String, ); } // 用于后续存本地的序列化方法 Map<String, dynamic> toJson() { return { 'branchcode': branchcode, 'role': role, 'name': name, }; } } class Loginuser { final String message; final String messagecode; final String token; final Userinfo userinfo; const Loginuser({ required this.message, required this.messagecode, required this.token, required this.userinfo, }); factory Loginuser.fromJson(Map<String, dynamic> json) { return Loginuser( message: json['message'] as String, messagecode: json['messagecode'] as String, token: json['token'] as String, // 解析嵌套的userinfo对象 userinfo: Userinfo.fromJson(json['userinfo'] as Map<String, dynamic>), ); } }
二、Token存储(用shared_preferences,新手友好)
- 在
pubspec.yaml添加依赖:
dependencies: shared_preferences: ^2.2.2
- 封装Token存取方法:
// 保存Token到本地 Future<void> saveToken(String token) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('auth_token', token); } // 从本地获取Token Future<String?> getToken() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('auth_token'); }
三、登录成功后用Go Router跳转
在登录按钮的点击事件中,完成登录请求后先存Token,再跳转首页:
void handleLogin(String mobile, String password) async { try { final loginResult = await fetchLoginuser(mobile, password); // 保存Token await saveToken(loginResult.token); // 跳转到首页(假设首页路由为'/home') if (context.mounted) { context.go('/home'); } } catch (e) { // 处理登录失败,比如弹窗提示 print('登录失败: $e'); } }
四、展示用户信息
方法1:全局变量存储(最简单)
定义全局类保存当前用户信息:
class GlobalUser { static Userinfo? currentUser; }
登录成功时赋值:
final loginResult = await fetchLoginuser(mobile, password); GlobalUser.currentUser = loginResult.userinfo;
首页直接调用:
Column( children: [ Text('用户名: ${GlobalUser.currentUser?.name ?? ''}'), Text('角色ID: ${GlobalUser.currentUser?.role ?? 0}'), Text('分支代码: ${GlobalUser.currentUser?.branchcode ?? 0}'), ], )
方法2:FutureBuilder(适合需要重新加载的场景)
如果需要从本地重新读取用户信息,先封装读取方法:
Future<Userinfo?> getUserInfo() async { final prefs = await SharedPreferences.getInstance(); final userInfoStr = prefs.getString('user_info'); if (userInfoStr != null) { return Userinfo.fromJson(jsonDecode(userInfoStr)); } return null; }
登录成功时同时存用户信息到本地:
await prefs.setString('user_info', jsonEncode(loginResult.userinfo.toJson()));
首页用FutureBuilder展示:
@override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<Userinfo?>( future: getUserInfo(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } else if (snapshot.hasData && snapshot.data != null) { final user = snapshot.data!; return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('欢迎你, ${user.name}'), Text('角色ID: ${user.role}'), Text('分支代码: ${user.branchcode}'), ], ); } else { return const Center(child: Text('未登录')); } }, ), ); }
内容的提问来源于stack exchange,提问作者Hari .S
相关产品推荐
相关产品推荐

