calculateRoute static method

TaskHandler? calculateRoute(
  1. List<Landmark> waypoints,
  2. RoutePreferences routePreferences,
  3. void onComplete(
    1. GemError err,
    2. List<Route> routes
    ), {
  4. void onStatusChanged(
    1. RouteStatus status
    )?,
})

Calculates routes between specified waypoints asynchronously.

Initiates an asynchronous route calculation using the provided waypoints and preferences. The method returns immediately with a TaskHandler to monitor or cancel the operation. Results or errors are delivered through the onComplete callback.

Requires at least 2 waypoints for path result types, or 1 waypoint for range result types (see RouteResultType for details). The calculation can be done offline, depending on the passed routePreferences and the availability of downloaded map data.

Returns null immediately only when the calculation cannot be initiated (invalid configuration detected synchronously). All other errors are delivered asynchronously through onComplete.

Parameters

  • waypoints: List of Landmark objects defining route start, end, and optional intermediate points. Must contain at least 2 waypoints for standard routes, or 1 waypoint for range calculations.
  • routePreferences: Configuration object specifying transport mode, route type, vehicle profile, restrictions, and calculation options.
  • onComplete: Callback invoked when calculation completes or fails. Called with:
    • GemError.success and non-empty routes list upon successful calculation.
    • GemError.notSupported and empty routes if preferences contain unsupported configuration (e.g., invalid transport mode combination).
    • GemError.invalidInput and empty routes if input is invalid (e.g., fewer than 2 waypoints for path result, or fewer than 1 for range result).
    • GemError.cancel and empty routes if calculation was cancelled via cancelRoute before completion.
    • GemError.waypointAccess and empty routes if no route could be found with given preferences (e.g., destination unreachable, no roads nearby).
    • GemError.connectionRequired and empty routes if online calculation is disabled (RoutePreferences.allowOnlineCalculation = false) and offline map data is insufficient for calculation.
    • GemError.expired and empty routes if offline map data is too old and no longer supported by online routing service.
    • GemError.routeTooLong and empty routes if online calculation exceeded server timeout (typically >1 minute, depending on server load).
    • GemError.invalidated and empty routes if offline map data changed (downloaded, erased, or updated) during calculation.
    • GemError.noMemory and empty routes if routing engine failed to allocate necessary memory for calculation.
  • onStatusChanged: Optional callback invoked whenever the calculation status changes, delivering the current RouteStatus (e.g. calculating, waitingInternetConnection, ready, error). Useful for reflecting progress in the UI while onComplete delivers the final result.

Returns

Example

TaskHandler? taskHandler = RoutingService.calculateRoute(
  [departureLandmark, destinationLandmark],
  routePreferences,
  (err, routes) {
    if (err == GemError.success) {
      // Do something with the calculated routes
    } else {
      print('Error: $err');
    }
  }
);

See also:

  • RoutePreferences - Configuration options for route calculation.
  • cancelRoute - Cancels an ongoing calculation.
  • Route - Calculated route with instructions and time/distance data.
  • NavigationService - Service for turn-by-turn navigation on routes.

Implementation

static TaskHandler? calculateRoute(
  List<Landmark> waypoints,
  RoutePreferences routePreferences,
  void Function(GemError err, List<Route> routes) onComplete, {
  void Function(RouteStatus status)? onStatusChanged,
}) {
  final EventDrivenProgressListener progListener =
      EventDrivenProgressListener();
  GemKitPlatform.instance.registerEventHandler(progListener.id, progListener);
  final RouteList results = RouteList();

  final LandmarkList waypointsList = LandmarkList.fromList(waypoints);

  if (onStatusChanged != null) {
    progListener.registerOnNotifyStatusChanged(
      (int status) => onStatusChanged(RouteStatusExtension.fromId(status)),
    );
  }

  progListener.registerOnCompleteWithData((
    int err,
    String hint,
    Map<dynamic, dynamic> json,
  ) {
    GemKitPlatform.instance.unregisterEventHandler(progListener.id);

    if (err == GemError.success.code) {
      // On web the native RouteList result can come back empty/misshaped in
      // some browsers (WASM-runtime dependent), which would otherwise crash
      // the whole app when the list is cast. Guard the read and degrade to a
      // general failure instead of throwing out of this callback.
      List<Route> routes;
      try {
        routes = results.toList();
      } catch (_) {
        onComplete(GemError.general, <Route>[]);
        return;
      }
      onComplete(GemErrorExtension.fromCode(err), routes);
    } else {
      onComplete(GemErrorExtension.fromCode(err), <Route>[]);
    }
  });

  final OperationResult result = staticMethod(
    'RoutingService',
    'calculateRoute',
    args: <String, dynamic>{
      'results': results.pointerId,
      'listener': progListener.id,
      'waypoints': waypointsList.pointerId,
      'routePreferences': routePreferences.pointerId,
    },
  );

  final GemError errorCode = GemErrorExtension.fromCode(result['result']);

  if (errorCode != GemError.success) {
    onComplete(errorCode, <Route>[]);
    return null;
  }

  return TaskHandlerImpl(progListener.id);
}