copyWith method

  1. @override
GpsStay copyWith({
  1. GpsTime? time,
  2. double? latitude,
  3. double? longitude,
  4. double? altitude,
  5. double? accuracy,
  6. GpsTime? endTime,
})
override

Create a copy of the point with optionally one or more of its fields set to new values.

It's a bit debatable what should happen with the endTime when copying from an original where _endTime == nul and modifying time for the copy without also modifying endTime for the copy.

Options for handling this situation would be:

  • Copy implicitly modifies endTime to maintain the duration of the original: copy.endTime - copy.time == original.endTime - original.time
  • Copy keeps endTime identical to the original, but shifts it to copy.time if copy would become invalid: copy.endTime == max(copy.time, original.endTime)
  • Maintain copy.endTime == original.endTime, and throw an exception if copy.time > original.endTime.

Additionally there's no way to reset endTime to null during the copy operation, except by calling the copyWith with an explicit endTime equal to time: c = s.copyWith(time: t, endTime: t);

There's no obviously superior choice, so the implementation chooses the strictest possible mode: leave endTime identical to the souce and throw an exception if that renders the copy invalid.

Implementation

@override
GpsStay copyWith(
    {GpsTime? time,
    double? latitude,
    double? longitude,
    double? altitude,
    double? accuracy,
    GpsTime? endTime}) {
  // Catch the issue explained in the documentation and throw an exception
  // here. This way the feedback will be more explicit if it happens at
  // runtime.
  final newTime = time ?? this.time;
  final newEndTime = endTime ?? _endTime;

  // Only perform the check if the caller is trying to modify times (saves
  // on relatively expensive time comparison).
  if (time != null || endTime != null) {
    // Caller is trying to modify times -> catch invalid configuration.
    if (newEndTime != null && newEndTime.isBefore(newTime)) {
      throw GpsInvalidValue(
          'Called $runtimeType.copyWith in a way that generates an invalid situation where endTime < time. Consider specifying the endPoint argument as well in the call.');
    }
  }

  return GpsStay(
    time: newTime,
    latitude: latitude ?? this.latitude,
    longitude: longitude ?? this.longitude,
    altitude: altitude ?? this.altitude,
    accuracy: accuracy ?? this.accuracy,
    endTime: newEndTime,
  );
}