Flutter中执行函数时为何对话框无法立即关闭?
问题:Flutter对话框关闭后执行函数时,对话框需等待函数完成才关闭
背景
想要在Flutter对话框关闭后执行删除操作,预期点击确认按钮后对话框立即关闭,删除操作在后台执行,但实际对话框要等删除函数执行完毕(约3秒)才会关闭。如果把删除函数替换成Future.delayed(Duration(seconds:5)),对话框能正常立即关闭。
相关代码
调用对话框的代码
Future<void> onDeleteEventData(BuildContext context) async { final title = context.messages.settings.offline.deleteEventData; final subTitle = context.messages.settings.offline.deleteEventDataDesc; final res = await showDeleteDialog(context, title: title, subTitle: subTitle); if (res == true){ context.read<EventDownloadTileController>().deleteEventRelatedData(); } }
自定义对话框调用函数
Future<bool?> showDeleteDialog(BuildContext context, {required String title, String? subTitle}) async { return await showDialog( context: context, builder: (_) => DeleteDialog(title: title,subTitle: subTitle,) ); }
对话框确认按钮点击事件
onPressed: () => Navigator.of(context).pop(true),
导致问题的删除函数
Future<void> deleteEventRelatedData() async { _ticketLoader.stop(); _ticketStorage.deleteScanTicketsForEvent(event.eventId); _eventStorage.deleteEventPermissions(event.eventId); _eventStorage.deleteEventData(event.eventId); _ticketStorage.deleteCachedTicketsForEvent(event.eventId); _ticketStorage.deleteCachedUnknownTicketsForEvent(event.eventId); _ticketLoader.updateLastSync(null); _ticketLoader.reset(); checkLocalStatus(); }
问题原因
核心原因是**deleteEventRelatedData虽标记为async,但内部的异步存储操作未加await**,导致这些操作以同步方式阻塞了主线程。
Flutter的UI渲染、用户交互都依赖主线程运行,当你调用deleteEventRelatedData()时,函数里的所有代码(包括那些未被await的异步操作的同步执行部分)会占用主线程,对话框关闭的UI更新任务被阻塞,必须等这些操作全部完成后,主线程空闲下来才能处理对话框关闭的逻辑。
而Future.delayed(Duration(seconds:5))是纯粹的异步延迟任务,会立刻被抛到事件队列,不会阻塞主线程,所以对话框能正常立即关闭。
解决方案
要实现对话框立即关闭、删除操作后台执行,需要两步调整:
- 给
deleteEventRelatedData里所有异步存储操作加上await,让异步操作真正挂起,不占用主线程; - 调用删除函数时无需
await(可用unawaited包裹避免IDE警告),让它在后台独立执行。
修改后的删除函数:
Future<void> deleteEventRelatedData() async { _ticketLoader.stop(); // 给所有异步存储操作添加await await _ticketStorage.deleteScanTicketsForEvent(event.eventId); await _eventStorage.deleteEventPermissions(event.eventId); await _eventStorage.deleteEventData(event.eventId); await _ticketStorage.deleteCachedTicketsForEvent(event.eventId); await _ticketStorage.deleteCachedUnknownTicketsForEvent(event.eventId); _ticketLoader.updateLastSync(null); _ticketLoader.reset(); checkLocalStatus(); }
调用时的修改(需导入package:flutter/foundation.dart使用unawaited):
if (res == true){ // 让函数后台执行,不阻塞当前流程 unawaited(context.read<EventDownloadTileController>().deleteEventRelatedData()); }
修改后,对话框会在点击确认后立即关闭,删除操作将在后台异步执行,不会阻塞主线程。
内容的提问来源于stack exchange,提问作者Yuki
相关产品推荐
相关产品推荐

