Skip to content

[Android] Fix MapHandler leaks when removed Pin instances are retained by app code - #35686

Merged
kubaflo merged 6 commits into
dotnet:inflight/currentfrom
SubhikshaSf4851:Fix-35571
Jun 5, 2026
Merged

[Android] Fix MapHandler leaks when removed Pin instances are retained by app code #35686
kubaflo merged 6 commits into
dotnet:inflight/currentfrom
SubhikshaSf4851:Fix-35571

Conversation

@SubhikshaSf4851

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment whether this change resolves your issue. Thank you!

This pull request improves the way map pin event subscriptions are managed in the MapHandler.Android implementation. The main change is to ensure that property change event handlers for map pins are only attached once, and are properly cleaned up, preventing duplicate subscriptions and potential memory leaks.

Description of Change

Pin subscription management improvements:

  • Introduced a _subscribedPins HashSet<IMapPin> field to track pins that have event handlers attached, ensuring each pin is subscribed only once.
  • Updated the AddPins method to only add a property changed event handler if the pin hasn't already been subscribed, using the _subscribedPins set.
  • Modified the DisconnectPins method to iterate over _subscribedPins instead of the pin list, removing event handlers from only those pins that were actually subscribed, and resetting the tracking set afterwards.

Regarding Tests :

No automated device test included. MapView.OnCreate throws IllegalStateException when no valid Google Maps API key is present — even an empty string value fails. This is the same constraint that keeps MapTests.cs behind #if IOS || MACCATALYST. Adding the key to AndroidManifest.xml would expose credentials in the repo, which is not acceptable.

Issues Fixed

Fixes #35571

Tested the behavior in the following platforms

  • Windows
  • Android
  • iOS
  • Mac
Before Issue Fix After Issue Fix
Fix35571Before.mov
Fix35571after.mov

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Jun 1, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@SubhikshaSf4851! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Jun 1, 2026
@PureWeen
PureWeen force-pushed the inflight/current branch from 1f8dd5f to 84345dc Compare June 2, 2026 20:09
@sheiksyedm
sheiksyedm marked this pull request as ready for review June 3, 2026 15:42
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

🔍 Skill Validation Results

✅ Static Checks Passed

Skills checked: 18 | Agents checked: 4

Full validator output
Found 2 skill(s)
[agentic-labeler] 📊 agentic-labeler: 2,839 BPE tokens [chars/4: 2,788] (standard ~), 8 sections, 0 code blocks
[agentic-labeler]    ⚠  Skill is 2,839 BPE tokens (chars/4 estimate: 2,788) — approaching "comprehensive" range where gains diminish.
[agentic-labeler]    ⚠  No code blocks — agents perform better with concrete snippets and commands.
[find-regression-risk] 📊 find-regression-risk: 967 BPE tokens [chars/4: 905] (detailed ✓), 10 sections, 2 code blocks
[find-regression-risk]    ⚠  No YAML frontmatter — agents use name/description for skill discovery.
✅ All checks passed (2 skill(s))
Found 4 agent(s)
Validated 4 agent(s)

✅ All checks passed (4 agent(s))

⏭️ LLM Evaluation: Skipped

💡 LLM evaluation was not run for this external PR.
A repository contributor can post /evaluate-skills on this PR to trigger full evaluation.

🔍 Full results and investigation steps

KarthikRajaKalaimani and others added 4 commits June 4, 2026 12:05
…net#34527)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Horizontalspacing / Verticalspacing is not not applied to the first
column in GridItemLayout using CollectionView on Android platform.
        
### Root Cause:

The grid spacing was not being distributed symmetrically across the
active layout implementations, so edge items did not fully participate
when spacing changed at runtime.

### Description of Change:

- On Android, the fix in MauiRecyclerView.cs changes how RecyclerView
padding is handled for GridItemsLayout. Android was already using
SpacingItemDecoration, which applies half-spacing on all four sides of
each item. Previously, negative RecyclerView padding canceled that
spacing at the control edges. The branch keeps that negative-padding
behavior for non-grid layouts, but disables it for GridItemsLayout,
allowing the grid’s half-spacing to remain visible at the outer
perimeter. This makes the first row and first column visually respond
when spacing changes, but it also changes the grid behavior from spacing
only between items to spacing around the outside edges as well.

**Tested the behavior in the following platforms:**

- [x] Android
- [x] Windows
- [ ] iOS
- [ ] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  dotnet#34257      

### Screenshots
| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/578dda69-1d60-474c-a6d8-23b3f9d29a50"
Width="300" Height="600"> | <Video
src="https://github.com/user-attachments/assets/7f3826e6-5922-4b6f-a6b9-de581b7db6c3"
Width="300" Height="600"> |
… is pushed onto a NavigationPage or Shell page with the back button disabled. (dotnet#35604)

Description of Change
Reverts Android and iOS fix from dotnet#28187.
Also reverts the iOS and macOS snapshot images
for `BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks` that
were resaved
 in dotnet#34760 as a follow-up to the dotnet#28187 fix

---------
@kubaflo

kubaflo commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 1 findings

See inline comments for details.

Comment thread src/Core/maps/src/Handlers/Map/MapHandler.Android.cs
@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Jun 4, 2026
MauiBot

This comment was marked as outdated.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you check the ai's suggestions?

@SubhikshaSf4851

Copy link
Copy Markdown
Contributor Author

Could you check the ai's suggestions?

@kubaflo i have checked the Ai summary and updated the suggested changes

@vishnumenon2684

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@kubaflo

kubaflo commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer

MauiBot

This comment was marked as outdated.

@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels Jun 5, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI Review Summary

@SubhikshaSf4851 — new AI review results are available based on this last commit: 4afe1e0.
Added suggestion To request a fresh review after new comments or commits, comment /review rerun.

Gate Skipped Code Review In Review Confidence High Platform Android

Review Sessions — click to expand
Gate — Test Before & After Fix

Gate Result: ⚠️ SKIPPED

No tests were detected in this PR.

Recommendation: Add tests to verify the fix using the write-tests-agent.


UI Tests

Full UI test matrix will run (no specific categories detected from PR changes).


Pre-Flight — Context & Validation

Issue: #35571 - [inflight regression] Android MapHandler leaks when removed Pin instances are retained by app code
PR: #35686 - [Android] Fix MapHandler leaks when removed Pin instances are retained by app code
Platforms Affected: Android
Files Changed: 1 implementation, 0 test

Key Findings

  • Android-only retained removed-pin leak was introduced by subscribing Pin.PropertyChanged without unsubscribing pins that had already been removed from Map.Pins before handler disconnect.
  • PR fix records every subscribed pin in a reference-equality HashSet<IMapPin> and disconnects/unsubscribes that tracked set, addressing retained removed pins and value-equal duplicate pins.
  • Gate was previously skipped because no tests were detected; the PR description says automated Android Map tests are blocked by Google Maps API key requirements.
  • GitHub CLI authentication was unavailable in this environment, so PR/issue context was fetched through unauthenticated GitHub API where possible.

Code Review Summary

Verdict: NEEDS_DISCUSSION
Confidence: high
Errors: 0 | Warnings: 1 | Suggestions: 0

Key code review findings:

  • ⚠️ CI is currently failing across required checks according to the code-review sub-agent; failures appear unrelated to this Android MapHandler diff but require CI triage before merge.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #35686 Track subscribed pins in HashSet<IMapPin>(ReferenceEqualityComparer.Instance) and unsubscribe/disconnect all tracked pins in DisconnectPins() ⚠️ Gate skipped; targeted Android Maps build passed locally src/Core/maps/src/Handlers/Map/MapHandler.Android.cs Original PR fix; code review found no code errors

Code Review — Deep Analysis

Code Review — PR #35686

Independent Assessment

What this changes: Android MapHandler now tracks pins it subscribed to and unsubscribes/disconnects those tracked pins during cleanup.
Inferred motivation: Fix retained removed-pin leaks and avoid duplicate PropertyChanged subscriptions.

Reconciliation with PR Narrative

Author claims: Fixes Android map pin subscription leaks for retained removed pins.
Agreement/disagreement: Agrees. Existing review feedback about value-equality HashSet was addressed with ReferenceEqualityComparer.Instance.

Findings

No high-confidence code findings. inline-findings.json contains [].

⚠️ Warning — CI is currently failing

Required checks are failing across maui-pr, maui-pr-devicetests, and maui-pr-uitests. The visible failures appear unrelated to this one-file Android MapHandler diff, but the PR is not merge-ready until CI is green or failures are triaged.

Devil's Advocate

I rechecked reconnect/repeated MapPins flow, removed-pin retention, duplicate subscriptions, and handler disconnect symmetry. The tracked-set approach appears sound and narrower than the old VirtualView.Pins cleanup.

Verdict: NEEDS_DISCUSSION

Confidence: high
Summary: Code change looks correct, but required CI is failing, so I cannot mark LGTM. Human/CI triage should confirm failures are unrelated or rerun to green.


Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 maui-expert-reviewer Disposable PinSubscription objects own marker updates and event unsubscription ❌ FAIL 1 file Failed Android build due unassigned marker outside IMapPinHandler branch
2 maui-expert-reviewer Reference-distinct active-pin snapshot/diff unsubscribes removed pins immediately on MapPins remap ✅ PASS 1 file Targeted Android Maps build passed; more proactive cleanup than PR fix
PR PR #35686 Reference-equality HashSet<IMapPin> tracks all subscribed pins and unsubscribes them in DisconnectPins() ⚠️ Gate skipped; targeted Android Maps build passed locally 1 file Original PR fix; simpler than candidate 2 but cleanup waits for remap/disconnect path

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Proposed disposable active-pin subscription snapshot; failed build because marker assignment was not guaranteed
maui-expert-reviewer 2 Yes Proposed active-pin snapshot/diff informed by candidate 1 failure; build passed

Exhausted: No
Selected Fix: Candidate #2 — It passed the available Android validation and is meaningfully different from the PR's fix by unsubscribing removed pins immediately when Map.Pins changes. It is not automatically recommended over the PR for merge because it is more complex and no automated leak regression test exists in this PR.


Report — Final Recommendation

Comparative Report — PR #35686

Candidates Compared

Rank Candidate Test Result Assessment
1 pr Gate skipped; targeted Android Maps build passed in prior context Best candidate. Fixes the retained removed-pin leak with a small, targeted change while preserving the existing Android MapPins teardown/rebuild lifecycle.
1 pr-plus-reviewer Same as pr Tied with pr because the expert reviewer found no actionable code feedback; the sandbox-applied reviewer candidate is identical to the raw PR fix.
3 try-fix-2 PASS Valid alternative and passed the targeted Android Maps build, but it is larger and changes subscription/handler lifecycle by retaining still-active pin handlers across marker rebuilds. That extra behavioral surface is not necessary to fix the leak.
4 try-fix-1 FAIL Must rank below passing candidates. It failed Android build with nullable/unassigned marker errors after moving marker ownership into PinSubscription.

Analysis

The raw PR fix changes cleanup from iterating the current VirtualView.Pins collection to iterating all pins the handler actually subscribed to. That is the narrow root-cause fix: removed pins are no longer missed during DisconnectPins(), reference-equal tracking prevents duplicate subscriptions, and reference equality avoids incorrectly coalescing distinct value-equal pins.

pr-plus-reviewer did not diverge from pr. The expert reviewer returned LGTM with no actionable inline findings, so there was no sandbox code change to apply. Its only recommendation was test coverage if Android Maps infrastructure can support it.

try-fix-2 is the strongest non-PR candidate. It passed the available targeted Android Maps build and also uses reference-based tracking, but it replaces the PR's all-subscribed set with an active-pin snapshot/diff. That makes removed-pin cleanup more selective, but it also removes the existing MapPins call to DisconnectPins() and keeps handlers for still-active pins while markers are removed and recreated. Because the PR fix already cleans removed pins on the same remap path with less lifecycle churn and less code, the additional complexity is not justified.

try-fix-1 is not viable because it failed regression validation at build time. Per the ranking rule, a failing candidate must be below all passing/skipped-but-build-validated candidates.

Winner

Winner: pr

The submitted PR fix is the best candidate because it is the smallest change that addresses the leak, preserves existing handler lifecycle behavior, and received no actionable expert-review findings. pr-plus-reviewer is equivalent, but pr is selected because no reviewer changes were actually applied.


Future Action — review latest findings

No alternative fix was selected for this run. Review the session findings and CI results before merging.

@kubaflo
kubaflo merged commit 4e82608 into dotnet:inflight/current Jun 5, 2026
30 of 50 checks passed
@github-actions github-actions Bot added this to the .NET 10.0 SR8 milestone Jun 5, 2026
PureWeen pushed a commit that referenced this pull request Jun 11, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
@sheiksyedm sheiksyedm modified the milestones: .NET 10 SR8, .NET 10 SR9 Jun 18, 2026
PureWeen pushed a commit that referenced this pull request Jun 22, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
kubaflo pushed a commit that referenced this pull request Jun 25, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
kubaflo pushed a commit that referenced this pull request Jul 3, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
@kubaflo kubaflo mentioned this pull request Jul 6, 2026
kubaflo pushed a commit that referenced this pull request Jul 6, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
kubaflo pushed a commit that referenced this pull request Jul 10, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
kubaflo pushed a commit that referenced this pull request Jul 15, 2026
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-map Map / Maps community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[inflight regression] Android MapHandler leaks when removed Pin instances are retained by app code

8 participants