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

Flutter中Beamer嵌套路由下安卓返回键异常问题

Flutter Beamer嵌套导航:物理返回键异常问题修复

问题现象

使用嵌套Beamer结构实现多级导航时,页面内返回图标可正常回退到上一级,但按下安卓物理返回键时,直接跳转到顶层Home页面,而非子导航栈的上一页。

问题原因

嵌套Beamer场景下,顶层BeamerBackButtonDispatcher会优先捕获物理返回事件,未将事件传递给子Beamer处理。子Beamer的导航历史栈未被顶层返回逻辑识别,导致直接回退到顶层Beamer的初始状态。

修复方案

1. 为子Beamer配置关联父Dispatcher的BackButtonDispatcher

在子Beamer所在的StatefulWidget中,创建专属的BeamerBackButtonDispatcher,并关联顶层Dispatcher,确保返回事件先由子Beamer处理。

修改ChefRootWidget:

class _ChefRootWidget extends State<ChefRootWidget> {
  int get storeId => widget.storeId!;
  late BeamerDelegate _routerDelegate;
  late BeamerBackButtonDispatcher _backButtonDispatcher;

  @override
  void initState() {
    _routerDelegate = BeamerDelegate(
      initialPath: '/home/chefMainWidget/chefStoreHomePage',
      locationBuilder: (routeInformation, _) {
        if (routeInformation.uri.toString().contains('/home/chefMainWidget/chefStoreHomePage')) {
          return ChefStoreBeamer(routeInformation, storeId);
        }
        return NotFound(path: routeInformation.uri.toString());
      },
    );
    // 关联父Dispatcher,让子Beamer优先处理返回事件
    _backButtonDispatcher = BeamerBackButtonDispatcher(
      delegate: _routerDelegate,
      parent: BeamerBackButtonDispatcher.of(context),
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Beamer(
        routerDelegate: _routerDelegate,
        backButtonDispatcher: _backButtonDispatcher, // 绑定到子Beamer
      ),
    );
  }
}

复现代码中ChildScreen的对应修改:

class _ChildScreen extends State<ChildScreen> {
  late BeamerDelegate _routerDelegate;
  late BeamerBackButtonDispatcher _backButtonDispatcher;

  @override
  void initState() {
    _routerDelegate = BeamerDelegate(
      initialPath: '/child-root',
      locationBuilder: (routeInformation, _) {
        if (routeInformation.uri.toString().contains('/child-root')) {
          return ChildLocation(routeInformation);
        }
        return NotFound(path: routeInformation.uri.toString());
      },
    );
    _backButtonDispatcher = BeamerBackButtonDispatcher(
      delegate: _routerDelegate,
      parent: BeamerBackButtonDispatcher.of(context),
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Beamer(
        routerDelegate: _routerDelegate,
        backButtonDispatcher: _backButtonDispatcher,
      ),
    );
  }
}

2. 完善BeamLocation的pathPatterns覆盖完整层级

子BeamLocation的pathPatterns需要包含所有可能的路径,确保Beamer能正确识别导航状态,维护历史栈。

修改ChefStoreBeamer:

class ChefStoreBeamer extends BeamLocation<BeamState> {
  final int storeId;

  ChefStoreBeamer(super.routeInformation, this.storeId);

  @override
  List<String> get pathPatterns => [
        '/home/chefMainWidget/chefStoreHomePage',
        '/home/chefMainWidget/chefStoreHomePage/chefStoreMenu/:menuId',
      ];

  // buildPages 代码保持不变
}

复现代码中ChildLocation的对应修改:

class ChildLocation extends BeamLocation<BeamState> {
  ChildLocation(super.routeInformation);

  @override
  List<String> get pathPatterns => [
        '/child-root',
        '/child-root/detail',
      ];

  // buildPages 代码保持不变
}

3. 跳转时明确操作子Beamer

使用Beamer.of(context, root: false)指定操作当前层级的子Beamer,避免误修改顶层导航栈:

Beamer.of(context, root: false).beamToNamed('/home/chefMainWidget/chefStoreHomePage/chefStoreMenu/$menuId');

修复原理

  • 子Beamer的BackButtonDispatcher通过parent属性与顶层Dispatcher联动,物理返回事件会优先由子Dispatcher处理,仅当子Beamer无历史可回退时,才传递给顶层。
  • 完整的pathPatterns确保Beamer正确匹配路径,维护准确的导航历史栈。
  • root: false参数确保跳转操作作用于当前子Beamer,避免干扰顶层导航状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:25:09