Flutter注册功能解析JSON响应展示用户提示消息实现方案
Flutter注册功能代码优化与正确实现
现有代码的几个明显问题
- 同一份接口响应反复调用
json.decode解析,完全没必要,既浪费性能,万一响应格式有问题还会重复触发报错 - 没加任何异常捕获,不管是请求超时、网络断开、返回格式不对,直接就崩,用户体验很差
- 注册成功分支光把模型转出来了,啥后续逻辑都没写,等于注册成功了用户啥反馈都收不到
- 错误提示写死的情况太多,状态码不对就弹
invalid data,根本不管接口实际返回了什么提示,而且没做空判断,万一接口返回的消息字段是空的,就弹个空白条,用户根本不知道出了啥问题 - 异步写法混乱,一会用
async/await一会用then,后面改逻辑很容易漏处理异常 - 你贴的响应模型只写了最外层的
RegisterResponse,里面依赖的Data、User这些类都没实现,直接运行肯定会报解析错误
优化后实现代码
首先补全响应模型缺失的内部类实现:
class Data { Data({User? user}) { _user = user; } Data.fromJson(dynamic json) { _user = json['user'] != null ? User.fromJson(json['user']) : null; } User? _user; User? get user => _user; Map<String, dynamic> toJson() { final map = <String, dynamic>{}; if (_user != null) { map['user'] = _user?.toJson(); } return map; } } class User { User({ String? firstName, String? username, String? email, int? type, int? roleId, int? verificationCode, int? verified, String? phone, String? updatedAt, String? createdAt, int? id, List<Map<String, int>>? balance, }) { _firstName = firstName; _username = username; _email = email; _type = type; _roleId = roleId; _verificationCode = verificationCode; _verified = verified; _phone = phone; _updatedAt = updatedAt; _createdAt = createdAt; _id = id; _balance = balance; } User.fromJson(dynamic json) { _firstName = json['first_name']; _username = json['username']; _email = json['email']; _type = json['type']; _roleId = json['role_id']; _verificationCode = json['verification_code']; _verified = json['verified']; _phone = json['phone'].toString(); _updatedAt = json['updated_at']; _createdAt = json['created_at']; _id = json['id']; if (json['balance'] != null) { _balance = []; json['balance'].forEach((v) { _balance?.add(Map<String, int>.from(v)); }); } } String? _firstName; String? _username; String? _email; int? _type; int? _roleId; int? _verificationCode; int? _verified; String? _phone; String? _updatedAt; String? _createdAt; int? _id; List<Map<String, int>>? _balance; Map<String, dynamic> toJson() { final map = <String, dynamic>{}; map['first_name'] = _firstName; map['username'] = _username; map['email'] = _email; map['type'] = _type; map['role_id'] = _roleId; map['verification_code'] = _verificationCode; map['verified'] = _verified; map['phone'] = _phone; map['updated_at'] = _updatedAt; map['created_at'] = _createdAt; map['id'] = _id; if (_balance != null) { map['balance'] = _balance; } return map; } }
然后是优化后的注册方法:
void _registration() async { // 统一获取输入内容 String name = _nameController.text.trim(); String email = _emailController.text.trim(); String password = _passwordController.text.trim(); String phone = _phoneController.text.trim(); // 输入校验,不通过直接return,避免冗余判断 if (name.isEmpty) { Utils.flushBarErrorMessage("请输入姓名", context); return; } if (email.isEmpty) { Utils.flushBarErrorMessage("请输入邮箱", context); return; } if (!GetUtils.isEmail(email)) { Utils.flushBarErrorMessage("请输入有效的邮箱地址", context); return; } if (password.isEmpty) { Utils.flushBarErrorMessage("请输入密码", context); return; } if (password.length < 6) { Utils.flushBarErrorMessage("密码长度不能少于6位", context); return; } if (phone.isEmpty) { Utils.flushBarErrorMessage("请输入手机号", context); return; } // 网络状态校验 var connectivityResult = await Connectivity().checkConnectivity(); if (connectivityResult != ConnectivityResult.mobile && connectivityResult != ConnectivityResult.wifi) { Utils.flushBarErrorMessage("当前无网络连接", context); return; } // 全链路异常捕获 try { final response = await ApiCall.signUp(name, email, password, phone); final responseJson = json.decode(response.body); // 只解析一次响应 RegisterResponse? registerModel; try { registerModel = RegisterResponse.fromJson(responseJson); } catch (e) { debugPrint("响应解析异常: $e"); Utils.flushBarErrorMessage("数据解析失败,请稍后重试", context); return; } // 优先取接口返回的提示,空值用本地文案兜底 String tipMsg = registerModel.enMessage ?? "请求异常,请稍后重试"; // 多语言场景可以在这里判断当前locale,选择取arMessage还是enMessage if (registerModel.success == true) { // 这里补自己的业务逻辑:比如本地持久化用户信息、跳转首页/验证页 debugPrint("注册成功,用户ID: ${registerModel.data?.user?.id}"); Utils.flushBarErrorMessage("注册成功", context); // 示例跳转:Get.offAllNamed(Routes.HOME); } else { Utils.flushBarErrorMessage(tipMsg, context); } } catch (e) { debugPrint("注册请求异常: $e"); Utils.flushBarErrorMessage("网络请求失败,请检查网络后重试", context); } }
几个要注意的点
- 提示文案永远优先用接口返回的内容,本地写死的文案只做兜底,避免出现提示和实际问题不匹配的情况
- 如果用GetX做状态管理,建议把注册逻辑挪到对应的鉴权控制器里,不要直接写在页面State中,后续维护成本会低很多
- 执行弹窗、路由跳转前最好判断下页面的
mounted状态,避免用户已经退出当前页面,后台还在执行UI操作导致报错 - 密码、手机号这类校验可以根据自己的业务规则加正则判断,不用完全照着示例写
内容的提问来源于stack exchange,提问作者user18710300
相关产品推荐
相关产品推荐

