flex mobile project : memory management - apache-flex

I have developed my first flex mobile application which is of TabbedViewNavigatorApplication. Application is working fine but when I test the application in "profile handler", memory usage goes on increasing as I navigate through the application. When I came to know that, I have to remove all the added eventlisteners and I have to nullify the objects which are no longer needed. When I switch between tabs , tabs are initialising again and again.
I dont know where can I remove the eventlisteners. I mean, I have written functions for each eventlisteners . Do I need to remove eventlistener when control goes to the function definition.
I have written sample code
var more:Image = new Image();
more.width = 70;
more.height=29;
more.x=10;
more.y=276;
more.source = "Assets/more button.png";
more.addEventListener(MouseEvent.CLICK, MORE_clickHandler);
mainGroup.addElement(more);
private function MORE_clickHandler(e:MouseEvent):void {
// Do I need to remove the eventlistener here
}
Also , do I need to explicitly nullify the object of Image class which I created or garbage collector will handle it. If I need to explicitly nullify it, where to do this.
Thanks

Garbage collection is an important part of any language, especially on mobile. Since mobile devices are a lot more limited than say our desktop counterparts, you need to be very careful what is being created/stored to memory. My motto is, if you don't see it, you shouldn't keep it. You can destroy views but keep their state using a view model.
To remove a view, you need to first remove it from the display list (removeElement(yourObject)), remove all event listeners, and nullify any referencing variable. If any variable still has a reference to it, it won't get garbage collected.
I recommend you read up a bit more on garbage collection as well as some neat tricks like pooling and virtualization (item renderers in a list).

You can setup an event listerener with a weak reference.
This implies that when the only reference to your object is the listener, the object itself can still be garbage collected and the listener will not keep it in memory.
The following will do the trick :
more.addEventListener(MouseEvent.CLICK, MORE_clickHandler,false, 0, true);
Another option would be to subclass the image class and let it implement an IDisposable interface, which would force you to implement a dispose() method.
Some handy resources:
http://www.intriguemedia.net/2007/09/24/when-to-use-weak-references
http://gskinner.com/blog/archives/2006/07/as3_weakly_refe.html
cheers

Related

Why it uses d->eventFilters.prepend(obj) not append(obj) in function(QObject::installEventFilter)

Why it uses d->eventFilters.prepend(obj) not append(obj) in function(QObject::installEventFilter),i want to know why design it in such way.I just curious about it.
void QObject::installEventFilter(QObject *obj)
{
Q_D(QObject);
if (!obj)
return;
if (d->threadData != obj->d_func()->threadData) {
qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
return;
}
// clean up unused items in the list
d->eventFilters.removeAll((QObject*)0);
d->eventFilters.removeAll(obj);
d->eventFilters.prepend(obj);
}
It's done that way because the most recently installed event filter is to be processed first, i.e. it needs to be at the beginning of the filter list. The filters are invoked by traversing the list in sequential order from begin() to end().
The most recently installed filter is to be processed first because the only two simple choices are to either process it first or last. And the second choice is not useful: when you filter events, you want to decide what happens before anyone else does. Well, but then some new user's filter will go before yours, so how that can be? As follows: event filters are used to amend functionality - functionality that already exists. If you added a filter somewhere inside the existing functionality, you'd effectively be interfacing to a partially defined system, with unknown behavior. After all, even Qt's implementation uses event filters. They provide the documented behavior. By inserting your event filter last, you couldn't be sure at all what events it will see - it'd all depend on implementation details of every layer of functionality above your filter.
A system with some event filter installed is like a layer of skin on the onion - the user of that system only sees the skin, not what's inside, not the implementation. But they can add their own skin on top if they wish so, and implement new functionality that way. They can't dig into the onion, because they don't know what's in it. Of course that's a generalization: they don't know because it doesn't form an API, a contract between them and the implementation of the system. They are free to read the source code and/or reverse engineer the system, and then insert the event filter anywhere in the list they wish. After all, once you get access to QObjectPrivate, you can modify the event filter list as you wish. But then you're responsible for the behavior of not only what you added on top of the public API, but of many of the underlying layers too - and your responsibility broadens. Updating the toolkit becomes next to impossible, because you'd have to audit the code and/or verify test coverage to make sure that something somewhere in the internals didn't get broken.

Flex: select tree node right after the dataProvider is been assigned / updated / replace

i have a Flex tree control and im trying to select a tree node 3 levels down right after the dataProvider is assigned with a collection object like the following.
basically treeItem1, treeItem2, treeItem3 are the nodes in the tree and treeitem3 is a child of treeItem2 which is a child of treeItem1. Assume these treeItem(1,2,3) are referenced correctly from the collection items.
my problem is that if i wait for the whole component to load completely then select the nodes, it open/select/scrolltoIndex correctly. However, if i were to select the node right after the dataProvider is assigned, then it doesn't even open or select (basically the this.treeService.selectedItem is always null).
can anyone point out what i did wrong? is there anything needs to happen after the dataProvider is assigned?
thanks
this.treeService.dataProvider = oPricingHelper.getCurrentPricingSercicesTreeSource();
this.treeService.expandItem(treeItem1, true);
this.treeService.expandItem(treeItem2, true);
this.treeService.selectedItem = treeItem3;
this.treeService.scrollToIndex(this.treeService.selectedIndex);
I have used the updateComplete event to know when a component (such as a DataGroup or List) has completed rendering after performing a simple task (such as updating the dataProvider reference). Of course, you have to be careful and remove listening to updateComplete because it can run a lot, unless you have a need for it to run.
Something like:
//...some function...
this.treeService.addEventListener(FlexEvent.UPDATE_COMPLETE, onTreeUpdateComplete);
this.treeService.dataProvider = oPricingHelper.getCurrentPricingSercicesTreeSource();
//...rest of some function...
private function onTreeUpdateComplete(event:FlexEvent):void {
this.treeService.removeEventListener(FlexEvent.UPDATE_COMPLETE, onTreeUpdateComplete);
this.treeService.expandItem(treeItem1, true);
this.treeService.expandItem(treeItem2, true);
this.treeService.selectedItem = treeItem3;
this.treeService.scrollToIndex(this.treeService.selectedIndex);
}
I'm not positive your experiencing the same issue but I seem to have the same type of problem with using the advanced data grid, it appears in these cases where the dataprovider is acceptable as multiple types, the components do some extra work in the background to wrap things up into something Hierarchical (HierarchicalData or HierarchicalCollectionView) and in doing so the dataprovider setter call is not synchronous (so it will return before actually having assigned the internal property storing the dataprovider). I've used callLater in this case with moderate success, callLater is generally a bad practice but basically adds a function to a list of functions to call once background processing is done, so this is assuming that something in the dataprovider setter called UIComponent.suspendBackgroundProcessing() and that it will subsequently call UIComponent.resumeBackgroundProcessing() and then it will execute the list of functions added by using callLater. Alternatively you could use setTimeout(someFunction,1000).
These are both "hacks" the real solution is to dig into the framework code and see what it's really doing when you tell it to set the dataprovider. Wherever you see that it actually has set the dataprovider you could extend that class and dispatch an event that you could listen for to run the function to do the selections after this point.
If anyone has a better solution please by all means correct me (I would love to have a better answer than this)

Forcing Flex to update the screen?

This may be a bit of a beginners question, but I can't for the life of me figure it out.
I'm using flex to develop a GUI for a large project, specifically a status bar along the bottom. Within my StatusBar class is a ProgressBar, which other classes doing work can tell to update(change bar completion and label) as they progress. The problem I'm encountering is that flex won't update whats shown on the screen until it's too late, for example
ProgressBar initialized, 0% done
some class sets the ProgressBar to be 12% done
some class does some work
some class sets the ProgressBar to be 56% done
Whats happening is the 12% done is never displaying, it just hangs at 0% during the work, then skips right to 56% done. I've tried to understand the lifecycle of a flex component (invalidation and validation), and I think I understand it and am applying it correctly, but it's not working at all. I need to tell flex to redraw my StatusBar (or at least the ProgressBar within) after some class sets it to be 12% done, but before some class starts doing its work. How do I do this?
As mentioned in other answers, the flash player is single threaded, if you don't break up your work into discrete chunks that can be executed in separate "frames", you're going to see jumps and stutters in the ui, which is effectively what you're seeing.
If you really must see that 12% message, then it's not enough to invalidate the display list, as the display list isn't getting a chance to update until after the 56% work has completed, you must explicitly interrupt the natural event cycle with a call to validateNow() after your message has been set.
This however is not the best way to do things if performance is of concern. You might get by with judicial usage of callLater() to schedule each chunk of work in turn, as this will allow the player to potentially complete a frame cycle (and update the display list) before attempting the next step in your process.
Glenn,
That is not at all how the threading in Flex works whatsoever. Like many UIs it has a message pump on the main UI thread (they do it in frames). When you call callLater() it places the passed in function pointer at the end of the message pump queue (on the next frame) and returns immediately. The function then gets called when the message pump has finished processing all of the messages prior (like mouse clicks).
The issue is that as the property change causes UI events to be triggered, they then place their own messages on the pump which now comes after your method call that you placed there from callLater().
Flex does have multiple threads but they are there for Adobe's own reasons and therefore are not user accessible. I don't know if there is a way to guarantee that a UI update will occur at a specific point, but an option is to call callLater a number of times until the operation occurs. Start off with a small number and increase until the number of iterations produces the result you want. Example:
// Change this to a number that works... it will probably be over 1, depending on what you're doing.
private const TOTAL_CALL_COUNT:int = 5;
private var _timesCalled:int = 0;
//----------------------------------------------------------------
private function set Progress( progress:int ):void
{
progressBar.value = progress;
DoNextFunction();
}
//----------------------------------------------------------------
private function DoNextFunction():void
{
if( _timesCalled >= TOTAL_CALL_COUNT )
{
_timesCalled = 0;
Function();
}
else
{
_timesCalled++;
callLater( DoNextFunction );
}
}
Try calling invalidateDisplayList() after each changes to your progress bar. Something like :
Class StatusBar
{
public function set progress(value:uint):void
{
progressBar.value = value;
progressBar.invalidateDisplayList();
}
}
Flex has an invalidation cycle that avoid screen redrawing everytime a property changes. As an example, if a property's value changes 3 times in a single frame, it will render only with the last value set. You can force a component to be redrawn by calling invidateDisplayList() which means updateDisplayList will be immediatly executed instead of waiting the next frame.
Actionscript in Flash player, like Javascript in the browser, is pseudo-multithreaded. That is, they're single threaded, but they have multiple execution stacks. This means you can't "sleep" in a particular thread, but you can spawn a new execution stack that gets deferred until a later time. The flex way of doing this is the "callLater" function. You can also use the setTimeout/setInterval functions. Or you can use a timer object built into the flash player. Or even "ENTER_FRAME" event listener. All of these will essentially allow you to do what you need, if I'm correct about the cause of your problems.
It sounds like you have one "thread" doing most of your work, never stopping to allow other execution stacks (threads*) to run.
The problem could be what PeZ is saying, but if that doesn't help, you might want to try some deferred calls for worker classes. So your process might look like this now:
Progress initialized.
Do some work.
Update progress bar to 12. (invalidate display list)
setTimeout(doMoreWork, 100);
Update progress bar to 52.
(if your worker is a UIcomponent, you can use uicomp.callLater(...), otherwise, you need to use setTimeout/timers/enter_frame for pure AS3 classes).
Sometimes its necessary set to zero before assign another value.
progressBar.setProgress(0, progressBar.maximum);
progressBar.setProgress(newValue, progressBar.maximum);
I'm using Flash Builder 4.6 and I also have a problem for the display of my progress bar. I open a new window where I start a new multiloader class (39 Mo of content). The new window is opened in background and the main window display a progress bar until the multiloader class has finished his work. However the opening window is blocking the animation of my main window. I know it's not the multiloader class cause I saw it running correctly.
But I will try to find some new ways of doing it.
The main purpose of my post is the complexity adobe has build around flash.
When you seek ressources for your own application or answers for your questions, it's a real pain to find the good ressource. There is a total mix up (at adobe side and at user side) between AS3, Flex, Flash CS, Flash Builder, AiR, ... If you try to develop in AS3, you will find that some examples won't work for you because it is not implemented in your SDK. You have more and more forums giving you the "best practice" or ironic answers based on experiences on different developping platform.
By example, just here above, I see progressBar.value = value; With my experience, I can say that in Flash Builder 4.6, this property is read-only. But It might be a custom class made by the user but who can tell.

AS3 Memory Conservation (Loaders/BitmapDatas/Bitmaps/Sprites)

I'm working on reducing the memory requirements of my AS3 app. I understand that once there are no remaining references to an object, it is flagged as being a candidate for garbage collection.
Is it even worth it to try to remove references to Loaders that are no longer actively in use? My first thought is that it is not worth it.
Here's why:
My Sprites need perpetual references to the Bitmaps they display (since the Sprites are always visible in my app). So, the Bitmaps cannot be garbage collected. The Bitmaps rely upon BitmapData objects for their data, so we can't get rid of them. (Up until this point it's all pretty straightforward).
Here's where I'm unsure of what's going on:
Does a BitmapData have a reference to the data loaded by the Loader? In other words, is BitmapData essentially just a wrapper that has a reference to loader.content, or is the data copied from loader.content to BitmapData?
If a reference is maintained, then I don't get anything by garbage collecting my loaders...
Thoughts?
Using AMF a bit with third party products has lead me to believe the Loader class attempts to instantiate a new class of the given content type (in this case it would be a Bitmap class instance). You are probably constructing a new BitmapData object from your Bitmap instance. From that I would assume that the Loader instance references the Bitmap instance, and in your case your code also references the Bitmap instance. Unless at some point you are calling BitmapData.clone().
There are also a couple of ways to force GC. Force Garbage Collection in AS3?
You may find it useful to attach some arbitrarily large object to something, then force the GC to see if that thing is getting cleaned up or floating around. If you are using Windows something like procmon (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) is more helpful than task manager for doing this kind of external inspection.
This of course is a bit trial and error but for lack of something like Visual VM (https://visualvm.dev.java.net/) we are kind of screwed in the Flash world.
It's a good question, but to the best of my knowledge, the answer is no -- neither Bitmap nor BitmapData objects possess references to the loaders that load them, so you can safely use them without concern for their preventing your Loaders from being collected.
If you want to make absolutely sure, though, use the clone() method of the BitmapData class:
clone()
Returns a new BitmapData object that
is a clone of the original instance
with an exact copy of the contained
bitmap.
For example:
private function onCreationComplete():void
{
var urlRequest:URLRequest = new URLRequest("MyPhoto.jpg");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_complete, false, 0, true);
loader.load(urlRequest);
}
private function loader_complete(event:Event):void
{
var img1:Image = new Image();
img1.source = Bitmap(event.target.content);
addChild(img1);
var img2:Image = new Image();
img2.source = new Bitmap(event.target.content.bitmapData.clone());
addChild(img2);
}
Here, img1's source is a Bitmap cast explicitly from the BitmapData object returned by the loader. (If you examine the references in FlexBuilder, you'll see they are identical.) But img2's source is a clone -- new bunch of bytes, new object, new reference.
Hope that helps explain things. The more likely culprits responsible for keeping objects from being garbage collected, though, are usually event handlers. That's why I set the useWeakReference flag (see above) when setting up my listeners, pretty much exclusively, unless I have good reason not to:
useWeakReference:Boolean (default =
false) — Determines whether the
reference to the listener is strong or
weak. A strong reference (the default)
prevents your listener from being
garbage-collected. A weak reference
does not.
you may set a variable in the complete listener that stores the bitmap and then destroy the object later
public function COMPLETEListener(e:Event){
myBitmap = e.target.loader.content;
}
public function destroy(){
if(myBitmap is Bitmap){
myBitmap.bitmapData.dispose();
}
}
works fine for me load some big image and see the difference in the taskmanager

Waiting while SWFLoader loads a swf file

Currently I'm working on an application (Flex) which heavily uses external SWFs.
I'd like to create a static method which takes a filename as an argument and returns SWF wrapped in some other class.
public static function getSWFWrapperFromFile(path:string):SWFWrapper {
var loader:SWFLoader = new SWFLoader();
loader.addListener(Event.COMPLETE, onLoad);
loader.load(path);
// If I create new SWFWrapper object here and try to assign it the loader.content I get null reference
}
However, with this approach I'm not able to encapsulate logic in one function, because of non-blocking load() and the need of onLoad handler. Is there possibility to force a delay after calling load method? Or mayber there is another, better way?
Thank you,
Alonzo
The display list is well-designed for asynchronous loading. You'll notice that Loader is a DisplayObject-derived class and thus can be placed directly in the display list. When its content is loaded it will be a child of the Loader. Thus, if SWFWrapper is DisplayObject-derived, you can simply do the following at the end of your code:
var wrapper:SWFWrapper = new SWFWrapper();
wrapper.addChild(loader);
return wrapper;
You need to wait until your Loader object has completed. Try adding in an event handler. Yes, the whole thing gets murky after a point of time when you have multiple loaders and and have to wait till the last one has completed. But that's the way it is if you are going to use SWFLoader.
In flash you cannot block in a method - you always have to use the onLoad handler for loading data. (The as3 execution model is single threaded, if you block in a method the rest of the program will not get executed)
Like others said, you can't do that. However, take a look at the BulkLoader AS3 library, which takes the burden of managing multiple loaders simultaneously and waiting for their completion, off your shoulder. It is well documented, and requires only a few lines to use.

Resources