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

为何移除空校验后变量仍为String?类型?Dart用shared_preferences存token报错

问题根因

你遇到的类型不匹配报错来自两个空安全逻辑叠加的结果:

  1. 你修改ResponseData类时移除了data属性的required修饰符,导致data被Dart自动推定为可空类型Map<String, String>?,本身就存在空值风险
  2. 即便data是非空Map,通过data["token"]方式取值时,只要对应key不存在就会返回null,所以拿到的token天然是String?类型,而shared_preferences的setString方法只接受非空String参数,二者类型不匹配触发报错,和Retrofit的空安全配置无关。

修复步骤

1. 修正响应类的空安全定义

恢复ResponseData中data属性的required修饰,接口异常无返回的情况会直接走异常捕获逻辑,不需要通过移除required兼容:

@JsonSerializable()
class ResponseData {
  @JsonKey(name: 'status')
  final int? statusCode;
  final Map<String, String> data;
  // 恢复required修饰,保证正常返回时data一定非空
  ResponseData({required this.data, this.statusCode}); 

  factory ResponseData.fromJson(Map<String, dynamic> json) => _$ResponseDataFromJson(json);
  Map<String, dynamic> toJson() => _$ResponseDataToJson(this);
}

2. 处理token取值的空值风险,三选一即可

  • 方案1:确定接口正常返回一定带token的场景,直接用!强制声明非空
_testToken.setString('token', value.data["token"]!);
  • 方案2:添加空值兜底逻辑,取不到token时默认存空字符串
_testToken.setString('token', value.data["token"] ?? '');
  • 方案3:先判空再执行存储,安全性最高,可同步添加异常处理
final String? token = value.data["token"];
if (token != null) {
  _testToken.setString('token', token);
} else {
  // 此处可添加登录失败提示逻辑
}

额外优化建议

建议将当前then链式调用改为async/await搭配try/catch的写法,可统一捕获网络异常、接口解析异常、返回值异常等问题,避免出现无提示闪退。


内容的提问来源于stack exchange,提问作者Wilson Toribio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:18:02