[Android] - Implement WindowInsetListener for per coordinator layout#31898
[Android] - Implement WindowInsetListener for per coordinator layout#31898NirmalKumarYuvaraj wants to merge 6 commits intodotnet:mainfrom
Conversation
|
Hey there @@NirmalKumarYuvaraj! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
| listener.RegisterCoordinatorLayout(coordinatorLayout); | ||
|
|
||
| // Set up event handlers for attach/detach | ||
| coordinatorLayout.ViewAttachedToWindow += (sender, e) => |
There was a problem hiding this comment.
Lambda captures create strong references and there is no cleanup/unsubscribe mechanism. Could improve it?
There was a problem hiding this comment.
@jsuarezruiz , I have updated changes. please let me know if you have any concerns.
981f11f to
b52a4e6
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the Android GlobalWindowInsetListener architecture from a global activity-level pattern to a localized CoordinatorLayout-based approach. Instead of having a single shared listener instance per activity, each CoordinatorLayout now manages its own listener instance which is tracked in a static registry.
Key changes:
- Replaced global activity-level listener with local per-CoordinatorLayout listeners tracked in a static registry
- Added
FindListenerForView()to locate the appropriate listener by traversing view hierarchy - Updated all call sites to use
FindListenerForView()instead ofContext.GetGlobalWindowInsetListener()
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| GlobalWindowInsetListener.cs | Core refactoring: added static registry, view hierarchy lookup methods, and CoordinatorLayout management |
| MauiAppCompatActivity.cs | Removed activity-level global listener property and lifecycle management |
| NavigationRootManager.cs | Changed to create and manage local listener for NavigationRootManager's CoordinatorLayout |
| SafeAreaExtensions.cs | Updated to use FindListenerForView instead of GetGlobalWindowInsetListener |
| MauiScrollView.cs | Updated to use FindListenerForView for configuration changes |
| LayoutViewGroup.cs | Updated to use FindListenerForView for configuration changes |
| ContentViewGroup.cs | Updated to use FindListenerForView for configuration changes |
| ViewHandler.Android.cs | Updated MapSafeAreaEdges to use FindListenerForView |
| WindowHandler.Android.cs | Added cleanup comment for local listener management |
| ModalNavigationManager.Android.cs | Removed separate modal listener management (now uses registry approach) |
| ShellSectionRenderer.cs | Added local listener setup and cleanup for Shell sections |
| ShellContentFragment.cs | Added local listener setup and cleanup for Shell content fragments |
| GlobalWindowInsetListener _localInsetListener; | ||
| CoordinatorLayout _managedCoordinatorLayout; |
There was a problem hiding this comment.
These fields should be marked with ? to indicate nullability since they are assigned after construction and set to null in Destroy(). This should be GlobalWindowInsetListener? _localInsetListener; and CoordinatorLayout? _managedCoordinatorLayout;.
| GlobalWindowInsetListener _localInsetListener; | |
| CoordinatorLayout _managedCoordinatorLayout; | |
| GlobalWindowInsetListener? _localInsetListener; | |
| CoordinatorLayout? _managedCoordinatorLayout; |
| GlobalWindowInsetListener _localInsetListener; | ||
| CoordinatorLayout _managedCoordinatorLayout; |
There was a problem hiding this comment.
These fields should be marked with ? to indicate nullability since they are assigned conditionally in OnCreateView() and set to null in Destroy(). This should be GlobalWindowInsetListener? _localInsetListener; and CoordinatorLayout? _managedCoordinatorLayout;.
| GlobalWindowInsetListener _localInsetListener; | |
| CoordinatorLayout _managedCoordinatorLayout; | |
| GlobalWindowInsetListener? _localInsetListener; | |
| CoordinatorLayout? _managedCoordinatorLayout; |
| // No locking needed since this runs on UI thread | ||
| static readonly List<CoordinatorLayoutEntry> _registeredCoordinatorLayouts = new(); |
There was a problem hiding this comment.
The comment assumes this always runs on the UI thread, but there's no enforcement. Consider adding thread safety or documenting the threading requirements more explicitly, especially since this is a static shared resource that could potentially be accessed from multiple contexts.
|
/rebase |
365c14b to
910f44e
Compare
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
| /// <summary> | ||
| /// Checks if a view is contained within the specified layout's hierarchy | ||
| /// </summary> | ||
| static bool IsViewContainedIn(AView view, ViewGroup layout) |
There was a problem hiding this comment.
Can trminate early if another CoordinatorLayout is found in the hierarchy that is not the target layout:
if (parent is CoordinatorLayout && parent != layout)
return false;
|
Moving this PR over to here |
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 if this change resolves your issue. Thank you!
Description of Change
This pull request introduces significant improvements to how safe area insets and window inset listeners are managed for Android in the MAUI codebase. The main enhancement is a new registry system for tracking
CoordinatorLayoutinstances and their associatedGlobalWindowInsetListeners, allowing for more precise and leak-free management of safe area insets, especially in complex navigation scenarios. Several components now use local listeners instead of a global one, and cleanup logic has been improved to avoid memory leaks.Safe area and window inset management improvements:
GlobalWindowInsetListenerto trackCoordinatorLayoutinstances and their local listeners, enabling views to find the appropriate listener for safe area updates. This includes new helper methods for registering, unregistering, and cleaning up listeners and layouts.ShellContentFragmentandShellSectionRendererto use localGlobalWindowInsetListenerinstances perCoordinatorLayout, including setup and cleanup logic to avoid cross-contamination and memory leaks.ViewHandler.Android.csto use the new registry-based approach for finding the correctGlobalWindowInsetListenerfor a view, replacing the previous context-based lookup and simplifying the logic for resetting safe areas.GlobalWindowInsetListenerinstances for modals, relying on the new registry system instead.ContentViewGroupandWindowHandler.Android.csto use the new registry-based listener lookup and clarified cleanup responsibilities when disconnecting handlers.These changes collectively make the handling of safe area insets more robust, modular, and less prone to memory leaks or incorrect inset application in complex navigation scenarios.
Fixes #