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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:57:16