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

Flutter中PopScope的onPopInvokedWithResult回调重复调用问题排查

PopScope的onPopInvokedWithResult回调重复触发的解决方案

问题背景

使用PopScope处理页面退出时的清理逻辑,发现onPopInvokedWithResult被触发两次:一次来自Navigator.maybePop(),另一次来自Navigator.didUpdateWidget()。已确认未使用自定义返回按钮、无重复调用pop()的情况。

解决方案

1. 给PopScope添加稳定Key(优先推荐)

问题根源在于GoRouter页面重建时,PopScope因缺少稳定Key被重新创建,导致Navigator触发额外回调。给PopScope绑定与页面一致的Key,确保实例复用:

@immutable
class MyRoute extends GoRouteData {

  const MyRoute({
    // ...
  });

  @override
  Page buildPage(BuildContext context, GoRouterState state) => MaterialPage(
        key: state.pageKey,
        child: PopScope(
          key: ValueKey(state.pageKey), // 添加稳定Key
          child: MyPageWithScaffold(
            // ...
          ),
          onPopInvokedWithResult: (didPop, result) {
            if (didPop) {
              doCleanup();
            }
          },
        ),
      );
}

2. 用状态标记控制清理逻辑执行(兜底方案)

在页面中维护一个执行标记,确保清理逻辑仅触发一次:

// 在MyPageWithScaffold的State类中添加
bool _hasExecutedCleanup = false;

void doCleanup() {
  if (!_hasExecutedCleanup) {
    _hasExecutedCleanup = true;
    // 执行实际清理操作
  }
}

如果是无状态组件,可通过StatefulBuilder或状态管理工具维护该标记。

3. 确保GoRoute参数的相等性判断正确

若MyRoute包含自定义参数,需正确重写==和hashCode,避免GoRouter因参数误判重复重建页面:

@immutable
class MyRoute extends GoRouteData {
  const MyRoute({
    required this.param1,
    required this.param2,
  });

  final String param1;
  final int param2;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is MyRoute &&
          runtimeType == other.runtimeType &&
          param1 == other.param1 &&
          param2 == other.param2;

  @override
  int get hashCode => Object.hash(runtimeType, param1, param2);

  @override
  Page buildPage(BuildContext context, GoRouterState state) => MaterialPage(
        // ...
      );
}

内容的提问来源于stack exchange,提问作者jeffrey.d.m

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 12:27:42