Flutter go_router如何将结果返回到上一页?

31

我想使用 go_router 包打开一个页面并获取返回结果。 在 Navigation 1.0 中,我使用以下代码:

final result = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const SecondRoute()),
);
// handle result

但是我似乎无法使用 go_router 来完成。 有解决方案或解释吗?

10个回答

17

最新版本的go_router包现在支持此功能。 要在从屏幕弹出时传递数据,您可以这样做:

context.pop('value');

为了获取这个值,你的代码应该像这样:

String? val = await context.pushNamed('secondRoute');

希望这能有所帮助,谢谢。

1
注意:此功能适用于版本6.5.0及以上。 - Giraldi

8
你可以使用GoRouter.of(context).addListener来完成这个操作。
首先你需要推入(push)你的新页面,然后再添加(add)一个监听器。
GoRouter.of(context).push("/page/${page!.id}/edit");
GoRouter.of(context).addListener(watchRouteChange);

监听器函数可以看起来像这样。
  watchRouteChange() {
    if (!GoRouter.of(context).location.contains("/edit")) {  // Here you check for some changes in your route that indicate you are no longer on the page you have pushed before
      // do something
      GoRouter.of(context).removeListener(watchRouteChange); // remove listener
    }
  }



2
在这种情况下如何获取返回结果? - Chris
1
问题要求将结果持久化,而这在你的代码中缺失了。 - Agni Gari
你在说什么? - A Andom Tamirat

3

目前,使用go_router无法实现此功能。您可以使用go_router_flow,它与go_router完全相同,并具有这个带值弹出的特性。

final bool? result = await context.push<bool>('/page2');

WidgetsBinding.instance.addPostFrameCallback((_) {
  if(result){
    print('Page returned $result');
  }
});

2

当推送新屏幕时,您可以通过将函数放在额外对象中来使用回调。

示例 屏幕A -推送-> 屏幕B ->带结果弹出-> 屏幕A(获取结果)

  1. 定义要放置的函数类型


typedef AddNewEventResult = void Function(Result result);


  1. 推送A-> B


GoRoute(
path: kScreenB,
builder: (BuildContext context, GoRouterState state) => ScreenB(addNewEventResultstate.extra! as AddNewEventResult),
)


  1. 当屏幕B完成后,只需从B弹出到A并附加结果(Result)


Navigator.of(context).pop();
widget.addNewEventResult(true, Result());



2
很遗憾,您正在寻找的功能 目前由GoRouter不提供
使用 go_router_flow 的替代方法是通过将回调作为 GoRouterState 上的 extra 属性进行传递来自己实现一些简单的东西。 这个dartpad 包含一个完整的示例,但要点是您可以定义类似于以下方式的路由:
GoRouter(
  initialLocation: "/",
  routes: <RouteBase>[
    GoRoute(
      path: "/second",
      builder: (_, state) {
        final params = state.extra! as SecondPageParams;

        return SecondPage(params: params);
      },
    ),
  ],
);

并将您的SecondPage定义类似于:
class SecondPageParams {
  final void Function(String data) action;
  
  const SecondPageParams(this.action);
}

class SecondPage extends StatelessWidget {
  final SecondPageParams params;

  const SecondPage({super.key, required this.params});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: ElevatedButton(
            onPressed: () {
              context.pop();
              params.action("Data from second page");
            },
            child: const Text("Pop and perform action")
          ),
        ),
      ),
    );
  }
}

这不如能够使用await context.push那样简洁明了,但这是一种简单的方法,你可以指定当SecondPage从堆栈中弹出时要执行的操作,而无需依赖于其他包。

1

0

截至回答时间,仅支持执行

 List<Archive> selectArchives = await Navigator.of(context).push(
            MaterialPageRoute(
                builder: (context) => const ArchiveListPage(
                    selectMode: true, canSelectCount: 1)));


 context.pop(_selectArchives);

-1

1
我不明白如何使用用户输入。您能否在此处添加代码,以便从屏幕2将数据返回到屏幕1(上一个屏幕)? - MaheshPeri19
当然。谢谢回复。 - MaheshPeri19
1
据我理解,文档基本上说使用go_router无法等待结果。它建议在“用户输入页面”中处理数据,并在保存数据后导航到其他页面而不返回原始页面。这意味着您无法创建一个简单的选择器屏幕(例如从全屏地图中选择一个地点)。您唯一能做的就是使用普通的导航器API并手动处理所有内容(例如:导航守卫、由路由器注入的基于路由的提供程序等)。 - Krisztián Velez
1
链接已失效。 - Chris
2
这是一个网页存档链接,因为该网站目前无法访问 https://web.archive.org/web/20220325235726/https://gorouter.dev/user-input - ahmetakil
显示剩余7条评论

-3

如果你使用Gorouter,你可以使用

GoRouter.of(context).pop();


目前你的回答不够清晰,请[编辑]以添加更多细节,帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

-7

当你完成下一个屏幕后,只需使用Navigator.pop(context, true);,其中true是你想发送到前一个屏幕的内容。你可以发送任何东西,我只是用true作为参考。这将允许你的result变量获取数据并执行任何操作。


你需要在第一页上访问第二页返回的数据吗?这是你想表达的吗? - Usama majid
我在询问go_router包的问题,而不是Navigator.push和Navigator.pop的工作原理,这个我知道。go_router不像Navigation 1.0那样返回Future。 - dante

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接