为何移除空校验后变量仍为String?类型?Dart用shared_preferences存token报错
问题根因
你遇到的类型不匹配报错来自两个空安全逻辑叠加的结果:
- 你修改
ResponseData类时移除了data属性的required修饰符,导致data被Dart自动推定为可空类型Map<String, String>?,本身就存在空值风险 - 即便
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
相关产品推荐
相关产品推荐

