Skip to content

[go_router] onExit not triggered for top-level route ("HomeScreen") #135094

@philitell

Description

@philitell

Is there an existing issue for this?

Steps to reproduce

@chunhtai It seems onExit is not triggered when using it on HomeScreen (refering to example https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/on_exit.dart).
E.g. using the android back-Button on HomeScreen (with onExit implemented on HomeScreen) closes the app without triggering onExit.
This usecase would be very usefull to show a dialog to the user to confirm closing the app.

Expected results

Using the android back-Button on HomeScreen (with HomeScreen beeing the last page on navigation stack) closes the app without triggering onExit.

Actual results

App is closed without triggering onExit

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

/// This sample app demonstrates how to use GoRoute.onExit.
void main() => runApp(const MyApp());

/// The route configuration.
final GoRouter _router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
      onExit: (BuildContext context) async {
        final bool? confirmed = await showDialog<bool>(
          context: context,
          builder: (_) {
            return AlertDialog(
              content: const Text('Are you sure to leave this page?'),
              actions: <Widget>[
                TextButton(
                  onPressed: () => Navigator.of(context).pop(false),
                  child: const Text('Cancel'),
                ),
                TextButton(
                  onPressed: () => Navigator.of(context).pop(true),
                  child: const Text('Confirm'),
                ),
              ],
            );
          },
      routes: <RouteBase>[
        GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
          onExit: (BuildContext context) async {
            final bool? confirmed = await showDialog<bool>(
              context: context,
              builder: (_) {
                return AlertDialog(
                  content: const Text('Are you sure to leave this page?'),
                  actions: <Widget>[
                    TextButton(
                      onPressed: () => Navigator.of(context).pop(false),
                      child: const Text('Cancel'),
                    ),
                    TextButton(
                      onPressed: () => Navigator.of(context).pop(true),
                      child: const Text('Confirm'),
                    ),
                  ],
                );
              },
            );
            return confirmed ?? false;
          },
        ),
        GoRoute(
          path: 'settings',
          builder: (BuildContext context, GoRouterState state) {
            return const SettingsScreen();
          },
        ),
      ],
    ),
  ],
);

/// The main app.
class MyApp extends StatelessWidget {
  /// Constructs a [MyApp]
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}

/// The home screen
class HomeScreen extends StatelessWidget {
  /// Constructs a [HomeScreen]
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () => context.go('/details'),
              child: const Text('Go to the Details screen'),
            ),
          ],
        ),
      ),
    );
  }
}

/// The details screen
class DetailsScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const DetailsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Details Screen')),
      body: Center(
          child: Column(
        children: <Widget>[
          TextButton(
            onPressed: () {
              context.pop();
            },
            child: const Text('go back'),
          ),
          TextButton(
            onPressed: () {
              context.go('/settings');
            },
            child: const Text('go to settings'),
          ),
        ],
      )),
    );
  }
}

/// The settings screen
class SettingsScreen extends StatelessWidget {
  /// Constructs a [SettingsScreen]
  const SettingsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Settings Screen')),
      body: const Center(
        child: Text('Settings'),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.13.4, on Ubuntu 22.04.3 LTS 6.2.0-33-generic, locale de_AT.UTF-8)
    • Flutter version 3.13.4 on channel stable at /home/user/snap/flutter/common/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 367f9ea16b (vor 7 Tagen), 2023-09-12 23:27:53 -0500
    • Engine revision 9064459a8b
    • Dart version 3.1.2
    • DevTools version 2.25.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /home/philipp/Android/Sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /snap/android-studio/127/android-studio/jbr/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop
    • clang version 10.0.0-4ubuntu1
    • cmake version 3.16.3
    • ninja version 1.10.0
    • pkg-config version 0.29.1

[✓] Android Studio (version 2022.2)
    • Android Studio at /snap/android-studio/126/android-studio
    • Flutter plugin version 75.1.1
    • Dart plugin version 222.4582
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[✓] Android Studio (version 2022.3)
    • Android Studio at /snap/android-studio/127/android-studio
    • Flutter plugin version 75.1.2
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] VS Code (version unknown)
    • VS Code at /snap/code/current
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
    ✗ Unable to determine VS Code version.

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Ubuntu 22.04.3 LTS 6.2.0-33-generic
    • Chrome (web)    • chrome • web-javascript • Google Chrome 115.0.5790.170

[✓] Network resources
    • All expected network resources are available.

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listfound in release: 3.13Found to occur in 3.13found in release: 3.14Found to occur in 3.14has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions