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
相关产品推荐
相关产品推荐

