如何解决Flutter登录中‘Null不是bool子类型’未处理异常
问题解决思路
核心原因
异常Unhandled Exception: type 'Null' is not a subtype of type 'bool'触发点在if (jsonBody['result'])这一行——你直接将jsonBody['result']当作布尔值判断,但该键对应的值为null,要么是后端返回的JSON里没有result字段,要么是字段名拼写错误。
修复步骤
先校验字段存在性
在判断result值前,先检查该键是否存在,避免强制转换null为bool:// 替换原有的if (jsonBody['result']) if (jsonBody.containsKey('result') && jsonBody['result'] == true) {修正键名的空格问题
代码中多处键名带多余空格(比如'id '、'id_user_type '),如果后端返回的键名没有空格,会导致取值为null,引发后续问题,需统一去掉空格:// 原错误写法 General.savePrefString(Const_Values.ID, jsonBody['id ']); General.savePrefString(Const_Values.ID_USER_TYPE, jsonBody['id_user_type ']); // 修正后 General.savePrefString(Const_Values.ID, jsonBody['id']); General.savePrefString(Const_Values.ID_USER_TYPE, jsonBody['id_user_type']); // 对应的类型判断也要同步修正 if(jsonBody['id_user_type'] == "2"){增加异常捕获与日志输出
为了快速排查后端返回的JSON结构问题,建议在解析后打印完整响应,同时捕获所有可能的异常:var jsonBody = jsonDecode(response.body); // 打印完整响应,方便排查结构问题 print('Login API Response: $jsonBody'); try { // 后续的登录逻辑 } catch (e) { print('Login Error: $e'); showDialog( context: context, builder: (context) => AlertDialog( icon: Icon(Icons.error), content: Text('登录失败,请稍后重试'), actions: [TextButton(onPressed: () => Navigator.pop(context), child: Text("OK"))], ), ); }后端接口格式校验
确认后端login.php返回的JSON必须包含result布尔字段,以及其他必要字段,示例正确格式:// 登录成功 {"result": true, "id": "1", "user_name": "xxx", "email_address": "xxx@xxx.com", "pas": "xxx", "id_user_type": "2"} // 登录失败 {"result": false, "msg": "邮箱或密码错误"}
完整修正后的代码
login() async { EasyLoading.show(status: 'loading...'); try { final response = await http.post( Uri.parse("${Const_Values.BASEURL}login.php"), body: {"email_address": emailControllor.text, "pas": passwordControllor.text}, ); EasyLoading.dismiss(); if (response.statusCode == 200) { var jsonBody = jsonDecode(response.body); print('Login API Response: $jsonBody'); if (jsonBody.containsKey('result') && jsonBody['result'] == true) { General.savePrefString(Const_Values.ID, jsonBody['id'] ?? ''); General.savePrefString(Const_Values.USER_NAME, jsonBody['user_name'] ?? ''); General.savePrefString(Const_Values.EMAIL_ADDRESS, jsonBody['email_address'] ?? ''); General.savePrefString(Const_Values.PASSWORD, jsonBody['pas'] ?? ''); General.savePrefString(Const_Values.ID_USER_TYPE, jsonBody['id_user_type'] ?? ''); if(jsonBody['id_user_type'] == "2"){ Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Main_Enduser_Serceen()), ); }else{ Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Main_Admin_Secreen()), ); } } else { showDialog( context: context, builder: (context) => AlertDialog( icon: Icon(Icons.error), content: Text(jsonBody['msg'] ?? '登录失败,请检查账号密码'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text("OK"), ), ], ), ); } } else { showDialog( context: context, builder: (context) => AlertDialog( icon: Icon(Icons.error), content: Text('服务器请求失败,状态码:${response.statusCode}'), actions: [TextButton(onPressed: () => Navigator.pop(context), child: Text("OK"))], ), ); } } catch (e) { EasyLoading.dismiss(); print('Login Exception: $e'); showDialog( context: context, builder: (context) => AlertDialog( icon: Icon(Icons.error), content: Text('网络异常,请检查网络连接'), actions: [TextButton(onPressed: () => Navigator.pop(context), child: Text("OK"))], ), ); } }
内容的提问来源于stack exchange,提问作者Lorans Alkhateeb
相关产品推荐
相关产品推荐

