flutter 中 go router 中 popUntil 的替代方案

kri*_*yaa 8 routes navigator dart flutter flutter-go-router

我想知道是否有 NavigatorpopUntil()方法的替代方法,或者有任何解决方法可以实现相同的目的。

如果我要使用Navigator. 我会像这样使用:

void _logout() {
  Navigator.popUntil(context, ModalRoute.withName('/login'));
}
Run Code Online (Sandbox Code Playgroud)

如何实现同样的目标go router


我看到一个 github 问题 - [go_router] Implement popUntil #2728,但没有相同的积极结果。

Acá*_*der 11


解决方法


虽然 @CommonSense 的答案有效,但也许我们可以稍微调整一下,当 GoRouter 无法弹出时避免弹出。

牢记这一点。最后,这只是一种解决方法,可能会导致意外行为,特别是将来 GoRouter 升级时。

void popUntilPath(String routePath) {
    
  final router = GoRouter.of(context);
  while (router.location != routePath) {

    if (!router.canPop()) {
      return;
    }

    debugPrint('Popping ${router.location}');
    router.pop();
  }
}
Run Code Online (Sandbox Code Playgroud)

正确的方式?


另一种方法(这似乎是正确的方法)是使用.go正确的路由声明,如下所示:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Go Router Demo',
      routerConfig: GoRouter(
        initialLocation: '/login',
        routes: [
          GoRoute(
            name: '/login',
            path: '/login',
            builder: (_, __) => const Login(),
            routes: [
              GoRoute(
                name: 'step-1',
                path: 'step-1',
                builder: (_, __) => const Step1(),
              ),
              GoRoute(
                name: 'step-2',
                path: 'step-2',
                builder: (_, __) => const Step2(),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

class Login extends StatelessWidget {
  const Login({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Entry Page')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Login entry page'),
            ElevatedButton(
              onPressed: () => GoRouter.of(context).pushNamed('step-1'),
              child: const Text('Go to step 1'),
            ),
          ],
        ),
      ),
    );
  }
}

class Step1 extends StatelessWidget {
  const Step1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Step 1')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Step 1'),
            ElevatedButton(
              onPressed: () => GoRouter.of(context).pushNamed('step-2'),
              child: const Text('Go to step 2'),
            ),
          ],
        ),
      ),
    );
  }
}

class Step2 extends StatelessWidget {
  const Step2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Step 2')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Step 2'),
            ElevatedButton(
              onPressed: () => GoRouter.of(context).goNamed('/login'),
              child: const Text('Go to login'),
            ),
          ],
        ),
      ),
    );
  }
}


Run Code Online (Sandbox Code Playgroud)

当您调用 时goNamed/login它会弹出直到登录,这就是您想要的。

如果您没有像这样声明路由(也许您正在使用命令式 API),GoRouter 将go访问该路由,但将其添加到堆栈中,而不仅仅是删除其他路由。


san*_*ari 6

去路由器:10.2.0

///Navigate back to specific route
void popUntilPath(BuildContext context, String routePath) {
 while (
  router.routerDelegate.currentConfiguration.matches.last.matchedLocation !=
      routePath) {
  if (!context.canPop()) {
  return;
  }
 context.pop();
 }
}
Run Code Online (Sandbox Code Playgroud)


小智 4

希望这可以帮助

while (GoRouter.of(context).location != "/") {
    debugPrint(GoRouter.of(context).location.toString()); //to get the routes in between
    GoRouter.of(context).pop();
}
Run Code Online (Sandbox Code Playgroud)