flutter_map icon indicating copy to clipboard operation
flutter_map copied to clipboard

[BUG] `TileLayer.reset` internal listener never triggers

Open weiweiMT opened this issue 1 year ago • 3 comments

What is the bug?

I was trying to use reset to trigger reload one of my TileLayer, but I found that the subsciption of reset never be initialized. In lib/src/layer/tile_layer.dart, the subscription of reset dosen't be triggered properly:

class _TileLayerState extends State<TileLayer> with TickerProviderStateMixin {
  bool _initializedFromMapCamera = false;

  final _tileImageManager = TileImageManager();
  late TileBounds _tileBounds;
  late var _tileRangeCalculator =
      TileRangeCalculator(tileSize: widget.tileSize);
  late TileScaleCalculator _tileScaleCalculator;

  // We have to hold on to the mapController hashCode to determine whether we
  // need to reinitialize the listeners. didChangeDependencies is called on
  // every map movement and if we unsubscribe and resubscribe every time we
  // miss events.
  int? _mapControllerHashCode;

  StreamSubscription<TileUpdateEvent>? _tileUpdateSubscription;
  Timer? _pruneLater;

  late final _resetSub = widget.reset?.listen((_) {
    _tileImageManager.removeAll(widget.evictErrorTileStrategy);
    _loadAndPruneInVisibleBounds(MapCamera.of(context));
  });

  // This is called on every map movement so we should avoid expensive logic
  // where possible.
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    final camera = MapCamera.of(context);
    final mapController = MapController.of(context);
.......

Because keyword "late" was used for _resetSub, and it never be accessed which means it will not be initialized. I tried to add one line "print(_resetSub);", then this subscription works. I think that might be bug.

How can we reproduce it?

  1. Include a TileLayer in your Flutter application.
  2. Pass a proper reset stream for the TileLayer, exactly same logic with the flutter map demo app.
  3. Trigger a reset event to observe the issue. (add break point inside the reset subsription will find the program doesn't get into it)

Do you have a potential solution?

Access it somewhere might be able to solve this problem.

Platforms

macOS, web

Severity

Minimum: Allows normal functioning

weiweiMT avatar Jan 22 '24 20:01 weiweiMT

Hi @weiweiMT, Thanks for reporting! I can reproduce this by adding a print statement (rather than a breakpoint) inside the reset stream listener. Before we look into fixing this, can I ask why this is required? Changing the URL should now work without using the reset stream (unlike in previous versions) - is there some sort of improper caching you're trying to invalidate? I'm just thinking it might be worth looking into removing it if there are better alternatives.

JaffaKetchup avatar Jan 31 '24 21:01 JaffaKetchup

@JaffaKetchup Thank you for your help! Thank you for looking into this! The reason we rely on the reset functionality is to make the TileLayer re-fetch the sonar raster data from GeoServer WMS. Since the URL remains constant, the TileLayer won't update on its own. However, for sonar data, we require real-time updates. The reset mechanism is crucial for ensuring the timely refresh of the TileLayer in our application. Appreciate your support!

weiweiMT avatar Feb 01 '24 13:02 weiweiMT

I've fixed the issue of the listener never firing, but it looks as though the issue from #1619/#1620 has returned, but that fix doesn't resolve the issue now. There's also some similarities to #1813. I think a fix in the TileImageManager is required.

JaffaKetchup avatar Feb 03 '24 12:02 JaffaKetchup