Currently, i’m experimenting with a very simple GUI drawing … “engine” (i guess you could call it that). The gist of it:
- there is a FrontController that gets hit by user requests; each request has a uid
- each uid (read “page”) has a declaration of the components (“modules”) that are present on it
- components are Sprite subclasses and, in essence, are unique
Naturally, i need a way of hiding/showing these sprites. Currently, i have it pretty much like Flex has it by default – in the way “if we are in a place where the comp is visible, create it, cache it and reuse it every time it’s visible again”.
The question is – which would be the more appropriate and efficient way of hiding and showing – via addChild/removeChild or toggling visible.
The way i see it is that:
visibleis quick and dirty (on first tests)visibledoes not create a chain of bubbling events likeEvent.ADDEDorEvent.REMOVED- invisible components don’t get mouse events
So removeChild would be something i’d call when i’m sure, that the component will no longer be necessary on the screen (or the cache is too big, for instance)
What do stackoverflow’ers / AS3-crazed people think?
Update:
Here’s a good read (forgot about google).
i will be sticking to visible; it seems to suit my task better; the manual “OPTIMIZING PERFORMANCE FOR THE FLASH PLATFORM” by Adobe on p. 69 gave me even more confidence.
here’s a code snippet i put up to test things for those that are interested:
package
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.utils.getTimer;
/**
* Simple benchmark to test alternatives for hiding and showing
* DisplayObject.
*
* Use:
* <code>
* new DisplayBM(stage);
* </code>
*
* Hit:
* - "1" to addChild (note that hitting it 2 times is expensive; i think
* this is because the player has to check whether or not the comp is
* used elsewhere)
* - "q" to removeChild (2 times in a row will throw an exception)
* - "2" to set visible to true
* - "w" to set visible to false
*
* @author Vasi Grigorash
*/
public class DisplayBM{
public function DisplayBM(stage:Stage){
super();
var insts:uint = 5000;
var v:Vector.<Sprite> = new Vector.<Sprite>(insts);
var i:Number = v.length, s:Sprite
while (i--){
s = new Sprite;
s.graphics.beginFill(Math.random() * 0xFFFFFF);
s.graphics.drawRect(
Math.random() * stage.stageWidth,
Math.random() * stage.stageHeight,
10,
10
);
s.graphics.endFill();
v[i] = s;
}
var store:Object = {};
store[Event.ADDED] = null;
store[Event.REMOVED] = null;
var count:Function = function(e:Event):void{
store[e.type]++;
}
var keydown:Function = function (e:KeyboardEvent):void{
var key:String
//clear event counts from last run
for (key in store){
store[key] = 0;
}
stage.addEventListener(Event.ADDED, count);
stage.addEventListener(Event.REMOVED, count);
var s0:uint = getTimer(), op:String;
var i:Number = v.length;
if (e.keyCode === Keyboard.NUMBER_1){
op = 'addChild';
while (i--){
stage.addChild(v[i]);
}
}
if (e.keyCode === Keyboard.Q){
op = 'removeChild';
while (i--){
stage.removeChild(v[i]);
}
}
if (e.keyCode === Keyboard.NUMBER_2){
op = 'visibile';
while (i--){
v[i].visible = true;
}
}
if (e.keyCode === Keyboard.W){
op = 'invisibile';
while (i--){
v[i].visible = false;
}
}
if (op){
//format events
var events:Array = [];
for (key in store){
events.push(key + ' : ' + store[key])
}
trace(op + ' took ' + (getTimer() - s0) + ' ' + events.join(','));
}
stage.removeEventListener(Event.ADDED, count);
stage.removeEventListener(Event.REMOVED, count);
}
//autodispatch
stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
}
}
}
Visible makes more sense to me (since removing a child indicates a finality) and is what I tend to use in my own projects when showing/hiding.
I’d also assume that addChild is slightly less performant but I haven’t done any tests.
EDIT: I just came across this Adobe article http://help.adobe.com/en_US/as3/mobile/WS5d37564e2b3bb78e5247b9e212ea639b4d7-8000.html which specifies that when using GPU rendering mode just setting visible = false can have a performance impact since there is a cost for drawing overlapping objects (even though they are not visible). Instead, removing the child entirely is advised: