I wrote UWP but this can be also on Android on IOS because I profiled only UWP application using VS2017.
Steps to create problem.
- Open VS 2017 and start a new xamarin forms project by selecting tabbed page or masterdetail page. No need to write any single code.
Problem;
First snapshot is after application is loaded.
2nd one has taken after selecting an item in the list and navigating to the ItemDetailsPage
3rd snapshot was taken after navigating back to ItemsPage
Expections; to not see ItemDetailsPage on 3rd snapshot because I am navigating back and this page is popped from the navigation stack. so it should be removed, collected by GC or disposed.
Here is the 3rd snapshot details;
Do I read this snapshot wrong or there is something wrong with the xamarin forms applications?
EDIT: Below screenshot also stats that there is "cycle detected". what does that mean? i thought cycles cause memory leaks, dont they?
not see ItemDetailsPage on 3rd snapshot because I am navigating back and this page is popped from the navigation stack. so it should be removed, collected by GC or disposed.
If you try navigating to different detailed pages then come back and take a snapshot again, you will find the count of ItemDetailPage stays 1.
Sometimes, for performance's sake, objects like page or resources will be properly cached and reused. If you have a page which contains large images or resources, you should try to dispose them manually to reduce memory usage.
Update:
Now question is how to properly dispose it? where to do that? I keep reading OnDissapearing method which is not safe for me as it can be called on navigating forward , not only navigating back in the stack. what is your suggestion for that?
If you don't want to dispose your resources for navigating forward, you can define a status parameter when navigating forward, do not dispose the resource. ex:
bool forwardNavigating=false;
...
protected override void OnDisappearing()
{
base.OnDisappearing();
if (!forwardNavigating)
{
//dispose your resources
}
}
elow screenshot also stats that there is "cycle detected". what does that mean? i thought cycles cause memory leaks, dont they?
cycle detected means:
An object can reference a second object that directly or indirectly holds a reference to the first object.
Please refer to Circular references of Analyze .NET Framework memory issues.
Personal thought:
I don't think it is a memory issue in terms of cycle detected. Under some situations we may need to visit parent object when we are in it's children. Thus we need a property Parent while the parent is still referencing the children. This happens a lot in views. I don't know how the analyzer works and whether it is the situation I described above. What I want to say is cycle detected doesn't equals Memory Leaks.
The same memory leak happens while dynamically changing the BindingContext (Reset the BindingContext by setting null and reassign the new view model) in Xamarin ListView. Does anyone come across this issue
DukeScript is quite clever in the way it handle changes to the Model so that code is hot-swapped at runtime, see for example here.
One thing it doesn't seem to handle at Runtime though is changes to the HTML layout. Given it runs in a WebView, a kind of a browse, it would nice just to be able to reload the page without having to stop and restart the app.
So, I've tried adding a "reload" button, but I can't find an easy way to do that after the initialization:
BrowserBuilder
.newBrowser()
.loadPage("pages/index.html")
.loadClass(Main.class).
invoke("onPageLoad", args).
showAndWait();
showAndWait() does what it's supposed to do, it doesn't return until the browser is closed. There doesn't seem any way to act on the underlying instance of a WebView and its thread.
Ha ha, simple but effective solution:
Reload
Note: Toni Epple says NetBeans would just detect the change, no reload needed.
I have been trying to pinpoint a memory leak I have in my flex application and I have just discovered that it might be related to mate.
I'm using mate's Injectors (in a mapping file) to inject an item to a popup:
<Injectors target="{MyTitleWindow}">
<PropertyInjector targetKey="item" source="{MyManager}" sourceKey="item" />
</Injectors>
I'm then using PopUpManager.addPopup and PopUpManager.removePopup to show/remove the popup but when I profile my application, I see that the count of MyTitleWindow objects only incline (removePopup does not free up the memory)
When I remove the injectors, everything works well ...
Has anyone encountered that issue? I guess I can override this issue by not using the injectors but I do hope there's a simpler solution ...
Edit
I've just learned that starting from version 0.8.8, PropertyInjector includes a property called softBinding which should (as I understand) fix this issue, but it doesn't ...
The Flex 3 docs are fairly basic. Can someone post a more complete example that uses the control's events? I'm still trying to get my head around ActionScript events.
You could find an interesting article concerning stateChange & playheadUpdate events on http://blog.flexexamples.com/2008/01/01/determining-a-videodisplay-controls-current-playback-state-using-the-state-property-and-statechange-event/
For a more complex example, take a look at the FXVideo component source code (in main unit FXVideo.as).
I have an application that loads external SWF files and plays them inside a Adobe Flex / Air application via the SWFLoader Flex component. I have been trying to find a way to unload them from a button click event. I have Google'd far and wide and no one seems to have been able to do it without a hack. The combination of code I see people use is:
swfLoader.source = ""; // Removes the external link to the SWF.
swfLoader.load(null); // Forces the loader to try to load nothing.
// Note: At this point sound from the SWF is still playing, and
// seems to still be playing in memory.
flash.media.SoundMixer.stopAll();
// Stops the sound. This works on my development machine, but not
// on the client's.
If the SWFs are closed (hidden) this way, eventually the program crashes.
Any ideas? I have found tons of posts in various forums with people having the same problem. I assume I will get one wrong/incomplete answer here, and than my post will sink into nothingness as usual, but either way, thanks in advance!
Edit 1: I can't edit the actual SWF movies, they're created by the client. If I can't close any SWF opened through Flex, isn't that a problem with the Flex architecture? Is my only option sending the SWFs to the web browser?
... isn't that a problem with the Flex architecture?
Yes it is, and it also affects Flash in general. Until you can take advantage of the Loader.unloadAndStop() method in FP10 (AIR 1.5), you can't guarantee that externally loaded content will not continue to consume memory and cpu resources, even if you use the Loader.unload() method. (To be honest, I'm not 100% sure that even that will guarantee freeing of resources, but maybe I'm a pessimist.)
The next best thing is for you to insist that the creators of the content you load adhere to a set of guidelines, including exposing something like a dispose() method which your app can call to ask it to release as many resources as possible before you unload() it. If this isn't possible, then your application will almost definitely bloat in memory and cpu usage each time you load an external swf. Sorry.
If it makes you feel any better, you're not alone. ;)
It is a problem that a badly created SWF can sink your application, and many of the issues with this will be fixed in Flash Player 10, as others have mentioned. However, regardless of platform you will always risk having problems if you load third party code, there's always the possibility that it contains bugs, memory leaks or downright malicious code. Unless you can load content into a sandbox (and you can't in Flash, at least not yet), loading bad things will sink your app, it's as simple as that.
I'm sorry to say that unless you can guarantee the quality of the loaded content you can't guarantee the quality of your own application. Flash developers are notorious for writing things that leak, or can't be unloaded, because Flash makes it easy to do the wrong thing, especially for things that live on the time line. Loading any Flash content that you don't have control over directly is very perilous.
The best solution is
swfLoader.autoLoad = false;
swfLoader.unloadAndStop();
swfLoader.autoLoad = true;
In this way you stop the player, unload the content from memory and avoid the sound to remain playing..
Cheers
The problem resides in the loaded swf, it simply does not clean up the audio after itself.
Try attaching an unload event onto movieclips like this:
MovieClip(event.target.content).loaderInfo.addEventListener(Event.UNLOAD, unloadMovieClipHandler);
private function unloadMovieClipHandler(event:Event) : void
{
SoundMixer.stopAll();
}
I'd generally stay away from SWFLoader and use the classes in the mx.modules package.
Flex has a module system that enables this type of behavior. You can check it out here : http://livedocs.adobe.com/flex/3/html/help.html?content=modular_3.html . In general, dynamically loading and unloading swf components is tricky, especially if those modules modify any global state in the application (styles, etc..). But if you create an interface for your modules, and then each class you load/unload implement that interface as well as extend the flex module class, you can load and unload them cleanly.
Try the following:
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
That will force a Garbage Collection routine. If your SWF is still attached, then you've missed some sort of connection, like the audio.
There are a couple ways to force GC, which all kind of suck because they spike CPU, but the good news is that an official way is coming in Flash Player 10:
unloadAndStop
link: http://www.gskinner.com/blog/archives/2008/07/unloadandstop_i.html
Until then, I'm afraid you'll have to force it with hacks like I showed above.
You have not shown all of your code so I am going to assume you didn't use the unload method of the Loader class. Also swfLoader.load(null) seems wrong to me as the load method is expecting a URLRequest object. When you want to clean things up at the end, set the object's value to null instead of calling a null load. The fact that your still hearing audio indicates that your data wasn't unloaded, or the audio file does not reside inside the content that was unloaded. Lets walk through this.
Example below
var loader:Loader = new Loader();
var request:URLRequest = new URLRequest('test.swf');
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSwfLoad, false, 0, true);
function onSwfLoad(e:Event):void
{
addChild(loader);
loader.contentLoaderInfo.addEventListener(Event.UNLOAD, onLoaderUnload, false, 0, true);
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onSwfLoad, false);
}
function onLoaderUnload(e:Event):void
{
trace('LOADER WAS SUCCESSFULLY UNLOADED.');
}
//Now to remove this with the click of a button, assuming the buttons name is button_mc
button_mc.addEventListener(MouseEvent.MOUSE_DOWN, onButtonDown, false, 0, true);
function onButtonDown(e:MouseEvent):void
{
loader.unload();
loader.contentLoaderInfo.removeEventListener(Event.UNLOAD, onLoaderUnload);
//When you want to remove things completely from memory you simply set their value to null.
loader = null;
button_mc.removeEventListener(MouseEvent.MOUSE_DOWN, onButtonDown);
}
I do hope that this was helpful, and I am sorry if it was redundant, but without seeing your code I have no way of knowing exactly how you approached this.