App注册时用户已入库但获取Token为Null报错求助
注册时Token保存报错(Null转String类型不匹配)的排查与解决
问题场景
注册用户已成功写入数据库,但保存Token时触发错误:type 'Null' is not a subtype of type 'String',相关代码如下:
class SignUpController extends GetxController { final isLoading = false.obs; final TextEditingController usernameController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); Future<void> signUpWithUsername() async { isLoading.value = true; final String username = usernameController.text.trim(); final String password = passwordController.text.trim(); // 调用后端注册接口 final response = await http.post( Uri.parse('${AppUrl.url}register'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{ 'username': username, 'password': password, }), ); if (response.statusCode == 201) { // 注册成功后提取Token final token = jsonDecode(response.body)['token']; // 解码Token获取用户信息 final Map<String, dynamic> decodedToken = JwtDecoder.decode(token); // 保存Token和用户信息 final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('token', token); await prefs.setString('user', jsonEncode(decodedToken)); // 跳转到首页 Get.offAllNamed(AppRoutes.home); } else { print('状态码: ${response.statusCode}'); print('响应体: ${response.body}'); Get.snackbar('错误', '响应内容: ${response.body}'.toString(), snackPosition: SnackPosition.BOTTOM); }
错误根源
从接口响应中提取的token为null,但后续的JWT解码、本地存储操作都要求它是String类型,直接触发类型转换异常。具体可能原因:
- 后端返回的响应体中没有
token字段,或者字段名拼写错误(比如实际是access_token) - 后端返回的
token值本身就是null
解决步骤
先确认接口返回结构
在注册成功分支里新增日志,打印完整响应体,排查字段问题:if (response.statusCode == 201) { print('注册响应体: ${response.body}'); // 新增日志 // 后续代码... }增加空值校验,提前拦截错误
修改Token提取逻辑,明确处理null情况:final responseData = jsonDecode(response.body); final String? token = responseData['token'] as String?; // 标记为可空类型 if (token == null) { Get.snackbar('错误', '注册成功但未获取到登录凭证', snackPosition: SnackPosition.BOTTOM); isLoading.value = false; return; }添加异常捕获,避免崩溃扩散
给Token解码和本地存储操作加上try-catch,处理其他潜在异常:try { final Map<String, dynamic> decodedToken = JwtDecoder.decode(token); final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('token', token); await prefs.setString('user', jsonEncode(decodedToken)); Get.offAllNamed(AppRoutes.home); } catch (e) { print('Token处理或存储失败: $e'); Get.snackbar('错误', '登录信息保存失败', snackPosition: SnackPosition.BOTTOM); } finally { isLoading.value = false; // 无论成功失败都重置加载状态 }修复加载状态遗漏问题
原代码中成功分支没有重置isLoading,会导致加载动画一直显示,必须在finally或成功分支末尾添加重置逻辑。
内容的提问来源于stack exchange,提问作者AykhanSh
相关产品推荐
相关产品推荐

