Skip to content

Fix MAUI MapControl memory leak (SKGLView not released after navigation) - #3273

Merged
pauldendulk merged 4 commits into
Mapsui:mainfrom
MereDoku:fix/maui-mapcontrol-memory-leak
Apr 25, 2026
Merged

pauldendulk merged 4 commits into
Mapsui:mainfrom
MereDoku:fix/maui-mapcontrol-memory-leak

Conversation

@MereDoku

Copy link
Copy Markdown
Contributor

Fixes #3271

Summary

This PR fixes a memory leak in Mapsui.Maui.MapControl where MapControl and the underlying
SKGLView were not garbage collected after navigating away from a page.

Repro

https://github.com/MereDoku/Mapsui.Maui.MemoryLeak.Repro

Changes

  • Disconnect MAUI handlers / clear native view references to allow GC
  • Stop MyLocationLayer animation on cleanup
  • Ensure MapView no longer keeps strong references after view is removed

How to test

  1. Run the repro project
  2. Navigate to MapPage and back multiple times
  3. Run VisualLeakCheckQueue.Monitor()
  4. Verify MapControl and SKGLView are collected

Platforms tested

  • WinUI ✅
  • Android ✅
  • iOS ✅

@pauldendulk pauldendulk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR — the problem is real and the fixes are correct.

What's good:

  • RenderController.Dispose() now unblocks the render loop (the .Set() calls are a genuine bug fix)
  • DataFetcher getting IDisposable with cancellation is the right approach
  • Android FixInvisible() infinite loop getting a CancellationToken is a clear improvement
  • MAUI handler disconnection via DisconnectHandler() is the correct MAUI pattern

Minor notes:

  • OpenInBrowserStatic is added in the constructor but SharedConstructor() already calls SetOpenInBrowserFunc — results in a redundant double call
  • TryStopMyLocationAnimations() — the "Try" prefix implies error tolerance that isn't there; StopMyLocationAnimations() would be more accurate
  • CleanupMapViewResources() calls Map.Layers.Clear() before base.Dispose() also clears layers — harmless but redundant

Architectural note:
The disposal code is now correct, but users still need to call Dispose() explicitly on navigation. A follow-up worth considering: overriding OnHandlerChanged() on the MAUI MapControl to call Dispose() automatically when Handler == null — that's the idiomatic MAUI lifecycle pattern and would make this fully transparent to users. This is something for a future PR.

@pauldendulk
pauldendulk merged commit 0d4652e into Mapsui:main Apr 25, 2026
5 checks passed
@pauldendulk

Copy link
Copy Markdown
Member

@MereDoku Sorry this review took so long!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR type: 🐛 Fix A bug fix or patch for existing functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MAUI 5.0.2] MapControl is not garbage collected after page navigation (SKGLView memory leak)

2 participants