maybePop<T extends Object?> method Null safety

  1. @optionalTypeArgs
Future<bool> maybePop<T extends Object?>(
  1. [T? result]
)
optionalTypeArgs">@optionalTypeArgs

Consults the current route's Route.willPop method, and acts accordingly, potentially popping the route as a result; returns whether the pop request should be considered handled.

If Route.willPop returns RoutePopDisposition.pop, then the pop method is called, and this method returns true, indicating that it handled the pop request.

If Route.willPop returns RoutePopDisposition.doNotPop, then this method returns true, but does not do anything beyond that.

If Route.willPop returns RoutePopDisposition.bubble, then this method returns false, and the caller is responsible for sending the request to the containing scope (e.g. by closing the application).

This method is typically called for a user-initiated pop. For example on Android it's called by the binding for the system's back button.

The T type argument is the type of the return value of the current route. (Typically this isn't known; consider specifying dynamic or Null.)

See also:

  • Form, which provides an onWillPop callback that enables the form to veto a pop initiated by the app's back button.
  • ModalRoute, which provides a scopedWillPopCallback that can be used to define the route's willPop method.

Implementation

@optionalTypeArgs
Future<bool> maybePop<T extends Object?>([ T? result ]) async {
  final _RouteEntry? lastEntry = _history.cast<_RouteEntry?>().lastWhere(
    (_RouteEntry? e) => e != null && _RouteEntry.isPresentPredicate(e),
    orElse: () => null,
  );
  if (lastEntry == null) {
    return false;
  }
  assert(lastEntry.route._navigator == this);
  final RoutePopDisposition disposition = await lastEntry.route.willPop(); // this is asynchronous
  assert(disposition != null);
  if (!mounted) {
    // Forget about this pop, we were disposed in the meantime.
    return true;
  }
  final _RouteEntry? newLastEntry = _history.cast<_RouteEntry?>().lastWhere(
    (_RouteEntry? e) => e != null && _RouteEntry.isPresentPredicate(e),
    orElse: () => null,
  );
  if (lastEntry != newLastEntry) {
    // Forget about this pop, something happened to our history in the meantime.
    return true;
  }
  switch (disposition) {
    case RoutePopDisposition.bubble:
      return false;
    case RoutePopDisposition.pop:
      pop(result);
      return true;
    case RoutePopDisposition.doNotPop:
      return true;
  }
}