-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Maui Embedded] DisconnectHandler not called when view is closed/disposed #18366
Comments
I have found a potential workaround, if I put this code in my ViewController, it will disconnect the handlers when I don't need them anymore:
Is this the recommended way of handling this? |
From this warning on the documentation it seems that is the expected behavior:
(I was expecting it to be called as well, I only discover this recently) |
I did not know this. Do any of the standard maui controls need disconnecting? It would be nice if the handlers could indicate that they require cleanup, and then on the parent have a DisconnectAllHandlers that cleans up what needs to be cleaned up. |
The problem is that we can't know when you want to disconnect the handler. For example, if you're moving a view from one layout to another layout you might not want it to disconnect. The guidance here is to use loaded/unloaded or the platform events related to being part of the visual tree to achieve what you want. You know more about your life cycle than we do :-) |
Hi @ultimategrandson. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time. |
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate. |
I accept that we should do the cleanup, its just knowing what actually needs to be cleaned up. Also, handlers don't implement IDisposable which I would normally intuit to meaning I need to manually clean up the resources of this myself. |
@PureWeen Please answer the question about whether MAUI controls are cleaned automatically and calling For example. Entry has some cleanup code. Who is gonna call DisconnectHandler for it? We are told by documentation to clean our controls but nothing about MAUI out of the box controls. Does MAUI clean them up somewhere?
|
I have the same question. I did a bit of testing using a custom handler that inherits from |
Is this for real? I just noticed that our DisconnectHandler was not called, which means we have a lot of memory leakage in our application right now. We are creating a library where we have a lot of event subscriptions going on, where we was 100% sure DisconnectHandler would run when the page was unloaded. If this is intentional, then this is completely different from the Xamarin way of disposing views, and right now I am not sure how we can create library UI components without having to add a lot of dispose code for each application we create. Please do something about this, add some very clever and easy way for us to dispose our views when the parent page is disposed... |
Edit: For anyone coming across this later, this below line of reasoning led me to create: https://github.com/AdamEssenmacher/MemoryToolkit.Maui to automate view cleanup
@PureWeen, I'm finding it hard to accept this line of reasoning. It's true that we cannot be absolutely certain about a given MAUI developer's intent regarding their view lifecycles. However, we can be reasonably certain about a given MAUI developer's intent regarding their view lifecycles 99% of the time... We want them cleaned up when they're removed from the Put another way, developers should be able to 'opt out' of handler disconnection on unload if needed. Requiring them to 'opt in' is backwards. @haavamoa, I'm not sure how 'clever' this is yet, as I'm just starting to explore the approach. I've written a couple of attached properties that you and others might find useful. The first looks like this in use:
Setting this attached property hooks into the To account for cases where we might want to selectively 'opt out' of this automatic disconnection behavior, a second attached property is provided:
If HandleDisconnectBehavior.Cascade encounters an element with this attached property, it will skip it and its children.
|
Nice @AdamEssenmacher , I also found out that I am referring to this line from my wiki page:
This means that you will have to make sure to "reconnect" everything when people navigate back to the page they came from, which is the page that has "disconnected". |
I've spent the better part of a week tracking down and fixing memory leaks in both third-party and standard MAUI controls on iOS and Android. Having gone deep down this rabbit hole, I'm starting to make some sense of the situation. First, let's clarify that the express purpose of calling This being said, calling Before I can explain the different effects
In MAUI world, the As an aside, this cascading leak effect can be mitigated by nulling out the Parent property of a leaking view. It won't stop the View itself from leaking, but by breaking the reference to the page you can prevent the leak spreading so massively. This could be a better-than-nothing stopgap for production apps suffering right now. Next, let's see how an individual View might become leaky by turning to the platform side. Each MAUI view (virtual view) is backed by a Handler, which connects it to the native platform view that is ultimately rendered on the screen. There is a circular reference between the virtual view and the handler. There is usually a circular reference between the platform view and the handler, but I don't think that's strictly necessary. So our total reference chain looks like this: This extends our cascading leak problem. Meaning, should a leak be introduced by the handler or platform view, the leak will spread through the virtual view to the page. How DisconnectHandler() comes into play
|
My workaround is the following: public class SomeHandler: ViewHandler<SomeView, UIView>
{
protected override void ConnectHandler(UIView platformView)
{
base.ConnectHandler(platformView);
VirtualView.AddCleanUpEvent();
}
protected override void DisconnectHandler(UIView platformView)
{
base.DisconnectHandler(platformView);
platformView.Dispose();
}
} public static class HandlerCleanUpHelper
{
public static void AddCleanUpEvent(this View view)
{
if (view is not Element element)
{
return;
}
Page? parentPage;
void PageUnloaded(object? sender, EventArgs e)
{
view.Handler?.DisconnectHandler();
if (parentPage is not null)
{
parentPage.Unloaded -= PageUnloaded;
parentPage = null;
}
}
foreach (var el in element.GetParentsPath())
{
if (el is Page page)
{
parentPage = page;
page.Unloaded += PageUnloaded;
}
}
}
// From MAUI source
public static IEnumerable<Element> GetParentsPath(this Element self)
{
Element current = self;
while (!IsApplicationOrNull(current.RealParent))
{
current = current.RealParent;
yield return current;
}
}
public static bool IsApplicationOrNull(object? element) =>
element == null || element is IApplication;
} |
Nobody wants to re-use the controls on a page after the page has been destroyed. For the time being, I will try to deal with this in @AdamEssenmacher workaround, but I hope it will be improved as MAUI. |
We faced issues with effect and behaviors causing leaks as well. To fix that you will have to do a .Clear() of the effects / behaviors once the page is not used anymore to get the Deattached methods to be invoked. We are have also noticed that UnLoaded events run when adding a modal page to the stack when a page is open, so be careful to not clean up a view that is a part of a page that pushes a modal page 😱 Our app is a Shell app, and we can use the Navigated Back events from Shell to know when to clean up instead of Unloaded for views. I still find it quite disturbing that disconnect/unattached/unloaded is not events that MAUI invokes onve a view is not used anymore, and that we as consumers of MAUI has the responsibility of figuring out a merhod to clean up. Real life scenario: This is of course (partially) our (the consumers) responsibility, and we have created patterns and pages that is not very performant or cleaned up, but we need to trust the framework to have some kind of event/method we can trust to use for clean up… In fact, our assumptions was initially that disconnect,unloaded and deattach was methods we could trust, without ever testing it until now :/ We will spend most of our time from August to solve this issue now, and hope it will be better for nurses and doctors 👍🏻 |
Please just introduce a breaking change for DisconnectHandler by changing the signature as well and modify all controls to Dispose/Disconnect themselves when the Page goes out of scope by MAUI. It's obvious that industry don't want to / can't handle something supposedly handled by the platform itself. It's not rocket science to detect in navigation stack that whether the page object is needed or not in app lifetime. Don't let years of hard work to be gone for nothing. It's an obvious architecture decision mistake going back years ago, but it's never too late to fix it. |
It seems that after the silence from MAUI team we have something on .NET MAUI updates in .NET 9 Preview 7 Summary
|
Seems like this is fixed or at least a way to work with in .NET 9. Thanks all! |
Description
I am assuming this is because of my application utilizing Maui Embedded. I am creating a view as per the documentation. However, when I close the ViewController, it does not call DisconnectHandler.
I noticed this when I was implementing a Barcode Reader (using the ZXing MAUI library), the cleanup code that stops the camera from running is in the DisconnectHandler method. When the view is closed, it does not call this and the camera remains running.
Is there a way to cleanup these handlers?
Steps to Reproduce
No response
Link to public reproduction project repository
No response
Version with bug
7.0.96
Is this a regression from previous behavior?
Yes, this used to work in Xamarin.Forms
Last version that worked well
Unknown/Other
Affected platforms
iOS, I was not able test on other platforms
Affected platform versions
No response
Did you find any workaround?
No response
Relevant log output
No response
The text was updated successfully, but these errors were encountered: