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

Flutter中使用API结合Model类实现登录及无法登录问题咨询

问题排查及修复方案

核心问题列表

  • JSON解析逻辑错误:接口返回的最外层结构是LoginModel,不是直接返回User对象,当前代码直接将完整响应体传入User.fromJson,必然解析失败
  • 网络层违规持有context:ApiManager作为通用网络封装类不应该持有BuildContext,也不应该处理页面跳转逻辑,跳转操作必须放在UI层执行
  • 异步方法未处理等待与异常:登录按钮点击时调用异步的loginUser方法没有加await,无法捕获请求过程中的异常,也无法保证请求完成后再执行后续操作
  • 请求参数名可能不匹配:当前POST请求传参为standardid、mediumid,需要确认后端接口要求的参数名是否为下划线格式standard_id、medium_id,参数名不匹配会导致后端无法正常接收参数
  • 未做参数合法性校验:点击登录时没有校验手机号、年级、介质是否已经选择/填写,空参数传给后端会直接被拦截
  • 请求头适配问题:http.post默认使用application/x-www-form-urlencoded格式传参,如果后端要求接收JSON格式参数,需要额外配置请求头并序列化请求体

修复代码

1. 修正apimanager.dart的loginUser方法

// 方法返回值改为LoginModel,移除context相关跳转逻辑
Future<LoginModel> loginUser(String mobile, String standardId, String mediumId) async {
  final loginUrl = "$baseUrl/user/login";
  final response = await http.post(
    Uri.parse(loginUrl),
    // 如果后端要求JSON格式传参,打开下面的headers配置,并把body用jsonEncode包裹
    // headers: {"Content-Type": "application/json"},
    body: {
      'mobile': mobile,
      // 确认参数名后替换,这里先改成下划线格式供参考
      'standard_id': standardId,
      'medium_id': mediumId,
    },
  );
  if (response.statusCode == 200) {
    final loginData = loginModelFromJson(response.body);
    // 可在这里加成功判断:if(loginData.success ==1) 再返回,否则抛异常
    if(loginData.success != 1){
      throw Exception(loginData.msg);
    }
    return loginData;
  } else {
    throw Exception('请求失败,状态码:${response.statusCode}');
  }
}

2. 修正login.dart的登录按钮点击逻辑

ElevatedButton(
  onPressed: () async {
    // 先做参数校验
    if(mobileController.text.trim().length != 10){
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("请输入正确的手机号")));
      return;
    }
    if(selectedStandard == null || selectedMedium == null){
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("请选择年级和介质")));
      return;
    }
    // 加载弹窗可选
    showDialog(context: context, barrierDismissible: false, builder: (ctx)=> const AlertDialog(content: Row(children: [CircularProgressIndicator(), SizedBox(width: 20), Text("登录中...")])));
    try {
      final loginResult = await ApiManager().loginUser(
        mobileController.text.trim(), 
        standardId, 
        mediumId
      );
      // 关闭加载弹窗
      Navigator.pop(context);
      // 登录成功跳转首页
      if(mounted){
        Navigator.push(context, MaterialPageRoute(builder: (context) => const DashBoard()));
      }
    } catch (e) {
      // 关闭加载弹窗
      Navigator.pop(context);
      // 提示错误信息
      if(mounted){
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("登录失败:${e.toString()}")));
      }
    }
  },
  child: const Text('Login'),
)

额外排查建议

  • 可以在请求时打印response.body查看后端实际返回的内容,确认是参数错误还是解析错误
  • 确认后端接口的请求方式、参数要求是否和当前调用逻辑一致

内容的提问来源于stack exchange,提问作者Dhaval Chaudhari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:27:01