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

Flutter中如何将API响应的成功/错误消息展示为SnackBar或弹窗

解决方案

方案1:直接调整现有逻辑快速实现

直接修改api_manager.dart中validateOtp方法的错误分支,翻译提示文案同时增加上下文合法性判断,避免页面销毁时弹窗报错:

else if (status == 0) {
  final apiMsg = validateOtpData.msg;
  // 英文提示翻译为中文,兜底异常提示
  String showMsg = apiMsg == "OTP is either expired or not valid." ? "OTP已过期或无效" : apiMsg ?? "验证失败,请稍后重试";
  final snackBar = SnackBar(content: Text(showMsg), backgroundColor: Colors.grey);
  // 仅页面存活时弹出提示
  if(context.mounted) {
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
  }
}

方案2:将响应结果返回给OTP页面自行处理(更灵活,可自由选择SnackBar/AlertDialog)

第一步:修改validateOtp方法返回结构

调整api_manager.dart的validateOtp方法,将验证状态和提示信息返回给调用页,同时增加异常捕获:

Future<Map<String, dynamic>> validateOtp(BuildContext context, String otp, LogedinUser? userData,
      UserPlan? userPlan) async {
  final String otpUrl = "$baseUrl/otp/validate";
  try {
    var formData = FormData.fromMap({
      'user_id': userData!.userId,
      'otp': otp,
      'device_id': userData.deviceId,
    });
    var response = await dio.post(otpUrl, data: formData);

    final validateOtpData = validateOtpFromJson(response.data);
    final status = validateOtpData.success;

    if (response.statusCode == 200) {
      if (status == 1) {
        // 验证成功跳转首页
        if(context.mounted) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => DashBoard(
                user: userData,
                userPlan: userPlan,
              ),
            ),
          );
        }
        return {"success": true, "msg": "验证成功"};
      } else {
        // 验证失败返回翻译后的错误信息
        String errorMsg = validateOtpData.msg == "OTP is either expired or not valid." ? "OTP已过期或无效" : validateOtpData.msg ?? "验证失败";
        return {"success": false, "msg": errorMsg};
      }
    } else {
      return {"success": false, "msg": "网络请求失败"};
    }
  } catch(e) {
    return {"success": false, "msg": "请求异常,请稍后重试"};
  }
}

第二步:修改OTP页面点击逻辑,拿到结果后自行弹窗

ElevatedButton(
  onPressed: () async {
    // 前置校验:OTP未输全时提前拦截
    if(otp.length != 6) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("请输入完整的6位OTP码")));
      return;
    }
    var result = await ApiManager().validateOtp(context, otp, userData, userPlan);
    if(context.mounted && !result["success"]) {
      // 方案A:弹出SnackBar,二选一即可
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(result["msg"]), backgroundColor: Colors.grey)
      );
      
      // 方案B:弹出AlertDialog,不需要则注释即可
      // showDialog(
      //   context: context,
      //   builder: (context) => AlertDialog(
      //     title: const Text("验证失败"),
      //     content: Text(result["msg"]),
      //     actions: [
      //       TextButton(onPressed: () => Navigator.pop(context), child: const Text("确定"))
      //     ],
      //   )
      // );
    }
  },
  child: const Text("Verify"),
)

优化建议

你当前代码中initState里的validateOtp调用可以删除,刚进入页面用户还未输入OTP,该调用无实际意义。

内容的提问来源于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.04 15:48:03