Flutter+GetX注册报错:type 'Null' is not a subtype of type 'String'
问题根因
你遇到的Unhandled Exception: type 'Null' is not a subtype of type 'String'是典型的空安全强转错误,代码里多处滥用强制非空操作符!,把实际为null的值强行赋值给非空String类型变量,具体触发点有4个:
- 注册页回调中直接使用
status.success!、status.enMessage!,只要接口返回字段缺失就会直接崩溃 - 注册成功分支中未做判空直接取
response.body["token"],传给要求非空String参数的saveUserToken方法,一旦接口200返回但没带token字段就会报错 - 请求失败分支中直接使用可空类型的
response.statusText赋值给非空参数,网络超时、域名解析失败时statusText本身就是null,直接触发类型错误 - ApiClient的请求头缺失
Content-Type: application/json配置,GetX默认post请求编码格式不是JSON,后端解析请求失败会返回非预期格式,导致所有响应字段解析为null
修复方案
按顺序改完下面的代码就能解决问题:
1. 修复注册页逻辑
替换原有注册方法代码,去掉强制非空,加入参校验:
void _freelancerRegistration(AuthController authController) { // 先校验表单入参,避免null值传给接口 if (name.isEmpty || email.isEmpty || password.isEmpty || phone.isEmpty) { Utils.flushBarErrorMessage("请填写完整注册信息", context); return; } SignUpBody signUpBody = SignUpBody( name: name, email: email, password: password, phone: phone); authController.registration(signUpBody).then((status) { // 用??操作符给空值兜底,禁止直接用!强转 if (status.success ?? false) { print('注册成功'); // 这里写注册成功后的跳转、存储逻辑 } else { Utils.flushBarErrorMessage(status.enMessage ?? "注册失败,请稍后重试", context); } }); }
2. 修复AuthController空安全问题
替换原有registration、login方法代码,所有可空字段都加判空兜底:
Future<ResponseModel> registration(SignUpBody signUpBody) async { _isLoading = true; update(); Response response = await authRepo.registration(signUpBody); late ResponseModel responseModel; if (response.statusCode == 200) { // 先判空再取token String? token = response.body?["token"]; if (token != null && token.isNotEmpty) { authRepo.saveUserToken(token); responseModel = ResponseModel(success: true, enMessage: "注册成功"); } else { responseModel = ResponseModel(success: false, enMessage: "返回数据异常,未获取到登录凭证"); } } else { // 给statusText加空兜底 responseModel = ResponseModel( success: false, enMessage: response.statusText ?? "网络请求失败,请检查网络连接"); } _isLoading = false; update(); return responseModel; } Future<ResponseModel> login(String email, String password) async { print('Getting Token'); print(authRepo.getUserToken().toString()); _isLoading = true; update(); Response response = await authRepo.login(email, password); late ResponseModel responseModel; if (response.statusCode == 200) { print('Backend Token'); String? token = response.body?["token"]; if (token != null && token.isNotEmpty) { authRepo.saveUserToken(token); print(token.toString()); responseModel = ResponseModel(success: true, enMessage: "登录成功"); } else { responseModel = ResponseModel(success: false, enMessage: "返回数据异常,未获取到登录凭证"); } } else { // 去掉原有的!强转,加空兜底 responseModel = ResponseModel( success: false, enMessage: response.statusText ?? "账号或密码错误"); } _isLoading = false; update(); return responseModel; }
3. 修复ApiClient请求头配置
给请求头加JSON格式声明,避免后端解析请求失败:
ApiClient({required this.appBaseUrl, required this.sharedPreferences}) { baseUrl = appBaseUrl; timeout = const Duration(seconds: 30); token = sharedPreferences.getString(AppConstants.TOKEN) ?? ""; _mainHeaders = { 'Content-Type': 'application/json; charset=UTF-8', 'Accept': 'application/json', 'Authorization': 'Bearer $token', }; } void updateHeader(String token) { _mainHeaders = { 'Content-Type': 'application/json; charset=UTF-8', 'Accept': 'application/json', 'Authorization': 'Bearer $token', }; }
4. 表单配置检查
确认你的name、email、password、phone四个表单变量默认值是空字符串'',而不是null,从源头上避免空值传入请求体。
调试技巧:后续遇到同类空类型报错,直接在Android Studio/VS Code里开启未捕获异常断点,报错时会直接定位到出错的代码行,不用逐行排查。
内容的提问来源于stack exchange,提问作者user18710300
相关产品推荐
相关产品推荐

