fix: stop syncing gesture positions back to mapProvider
Removed the updateCamera() call from onPositionChanged. Previously, every gesture-driven pan/zoom frame updated the provider state, which triggered ref.listen to call _mapController.move() redundantly. This caused flutter_map's TileLayer to cancel in-flight tile loads on every frame — producing partially-rendered maps and crashes when zooming out during tile loading. The ref.listen now only fires for programmatic changes (locateUser, zoomIn/zoomOut), which are infrequent single-shot moves. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
578d2d24ed
commit
a3aaf1b6de
1 changed files with 11 additions and 17 deletions
|
|
@ -41,20 +41,14 @@ class _MapScreenState extends ConsumerState<MapScreen> {
|
|||
final apiClient = ref.watch(apiClientProvider);
|
||||
final styleAsync = ref.watch(mapStyleProvider(apiClient.baseUrl));
|
||||
|
||||
// Listen for zoom/center changes from the provider and move the map.
|
||||
// Skip the move if the map controller is already at the target position
|
||||
// (meaning the state change came from a user gesture via onPositionChanged).
|
||||
// Without this guard, every gesture-driven pan calls _mapController.move()
|
||||
// with the position the map is already at, which triggers a tile
|
||||
// recalculation that cancels in-flight tile loads and produces a
|
||||
// partially-rendered (diagonal) map.
|
||||
// Move the map only for programmatic state changes (locateUser,
|
||||
// zoomIn/zoomOut). Gesture-driven pans no longer call updateCamera(),
|
||||
// so this listener only fires for intentional moves and won't interfere
|
||||
// with the TileLayer's in-flight tile loads.
|
||||
ref.listen<MapState>(mapProvider, (previous, next) {
|
||||
if (previous?.center != next.center || previous?.zoom != next.zoom) {
|
||||
final camera = _mapController.camera;
|
||||
if (camera.center != next.center || camera.zoom != next.zoom) {
|
||||
_mapController.move(next.center, next.zoom);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
|
|
@ -69,12 +63,12 @@ class _MapScreenState extends ConsumerState<MapScreen> {
|
|||
minZoom: 0,
|
||||
maxZoom: 18,
|
||||
onPositionChanged: (position, hasGesture) {
|
||||
if (hasGesture) {
|
||||
ref.read(mapProvider.notifier).updateCamera(
|
||||
position.center,
|
||||
position.zoom,
|
||||
);
|
||||
}
|
||||
// Intentionally not syncing gesture-driven position changes
|
||||
// back to the provider. Doing so caused ref.listen to call
|
||||
// _mapController.move() on every pan/zoom frame, which made
|
||||
// flutter_map's TileLayer cancel in-flight tile loads —
|
||||
// producing a partially-rendered (diagonal) map and crashes
|
||||
// when zooming out during tile loading.
|
||||
},
|
||||
onTap: (tapPosition, point) {
|
||||
ref.read(mapProvider.notifier).clearSelectedPlace();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue