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

Flutter中showDialog导航后重建致请求重复执行的问题及解决方案

解决Flutter中showDialog builder重复执行导致请求两次的问题

问题根源

Flutter的showDialog的builder回调会在widget树重建时被多次触发(比如导航操作可能引发父组件重建)。你之前直接在builder里调用sendAttendanceRequest(context),每次builder执行都会重新发起请求,这就是请求被调用两次的原因。

修正方案

核心思路是提前创建请求的Future实例,不让builder重复触发请求:

  • 在调用showDialog之前就执行请求并保存Future,确保请求只发起一次
  • 导航前加mounted判断,防止widget销毁后使用context报错
  • 完善请求的异常处理,避免请求失败导致流程异常

修正后的代码

onPressed: () async {
  // 提前发起请求并保存Future,确保只调用一次
  final requestFuture = sendAttendanceRequest(context);
  
  await showDialog(
    context: context,
    builder: (context) {
      return FutureProgressDialog(
        requestFuture, // 传入提前创建好的Future实例
        progress: const CircularProgressIndicator(),
        opacity: 0.7,
        decoration: const BoxDecoration(
          color: Colors.transparent,
          borderRadius: BorderRadius.all(Radius.circular(4)),
        ),
      );
    },
  );
  
  // 确保当前widget还挂载时再导航,避免context错误
  if (mounted) {
    context.pushReplacementNamed(SCREENS.attendances.toName);
  }
}

Future<void> sendAttendanceRequest(BuildContext context) async {
  try {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final response = await http.post(
      Uri.parse('${Server.baseURL}/api/v1/attendance/request'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': prefs.getString('token') ?? "",
      },
      body: jsonEncode({
        "type_request": _attendanceId == "" ? "create" : "edit",
        "attendance_id": _attendanceId,
        "description": _descriptionController.text,
        "project_id": _selectedProjectId,
        "started_at": _combineDateTime(_clockInDate, _clockInTime),
        "ended_at": _combineDateTime(_clockOutDate, _clockOutTime),
      }),
    );

    // 可选:根据响应状态处理成功/失败逻辑
    if (response.statusCode != 200) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('打卡请求失败')),
        );
      }
    }
  } catch (e) {
    // 捕获网络异常等错误
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('请求出错: $e')),
      );
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:40:18