Flutter如何等待Navigator.pop动画完成后执行后续逻辑
Flutter 路由pop后等待页面销毁再执行业务逻辑的规范实现
固定写1秒延迟的方案存在明显缺陷:
- 时序不可靠:设备性能差、用户手动调长系统动画时长时,1秒后页面可能还未完成dispose,执行删除仍会触发组件已卸载时的状态操作报错;动画时长短于1秒时又会产生无意义等待,拖慢操作响应速度。
核心原因:
Navigator.push返回的Future在pop方法被调用的瞬间就会resolve返回结果,此时路由离场动画才刚启动,被关闭的页面仍存在于Widget树中,并未走完dispose流程。要解决问题只需要准确拿到路由离场动画完成、页面完全销毁的时机即可,不需要硬编码等待时间。
推荐实现:监听路由实例生命周期
不需要新增全局路由监听,只需要微调原有跳转逻辑,直接持有路由对象等待离场流程全部完成即可,代码如下:
onTap: () async { // 先创建路由实例 final entityRoute = MaterialPageRoute<MyPageResult>( builder: (_) => MyEntityPage(id: id), ); // 发起路由跳转,拿到结果返回的Future final resultFuture = Navigator.push(context, entityRoute); // 构造路由完全销毁的等待Future:先等pop触发,再等转场动画全部执行完成 final routeDisposed = entityRoute.popped.then((_) => entityRoute.completed); // 同时等待结果返回、页面完全销毁两个条件 final result = await resultFuture; await routeDisposed; if (result == MyPageResult.delete) { // 此时页面已完全dispose,动画执行完毕,直接执行删除逻辑即可 ref.read(dataProvider.notifier).deleteEntity(id: id); } }
关键API说明
route.popped:路由触发pop操作时完成,对应页面开始执行离场流程的节点route.completed:路由所有转场动画(入场/离场)全部执行完毕、路由完全从路由栈移除、对应页面走完dispose流程后才会触发,该时机完全跟随系统实际动画时长,不受设备性能、用户动画设置影响,时序100%准确。
扩展场景方案
如果项目中多个页面都存在类似“等页面完全退出再执行操作”的需求,可以自定义NavigatorObserver统一监听路由销毁事件做全局处理,单页面场景下上述实现成本最低,也最灵活。
内容的提问来源于stack exchange,提问作者Tien Do Nam
相关产品推荐
相关产品推荐

