Zurück   Flashforum > Flash > ActionScript > ActionScript 3

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 18-01-2008, 21:15   #1 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
Post DisplayObjectContainer - Rekursive children-Entfernung

Hallo zusammen,

hab grad eine kleine rekursive Funktion geschrieben, die mir sämtliche children EINES BESTIMMTEN DisplayObjectContainers von der Bühne haut und auch diesen bei Bedarf (2. Parameter = true) entfernt.

Keine Ahnung ob ihr sowas brauchen könnt, oder obs für euch überhaupt Sinn macht, aber ich hatte es dringend gebraucht, weil der garbageCollector sonst nicht so klar kommt wie ich mir das wünsche. Und da ich an einem NewsDisplay arbeite gibts da ne Menge children

Die Funktion geht einfach rekursiv alle children durch und entfernt sie über parent.removeChild...


Falls ihr Verbesserungsvorschläge habt, oder auch ganz andere Ansätze wie ihr das Entfernen von DisplayObjects und Containern regelt wär ich euch natürlich dankbar.

Ansonsten hoff ich, dass der Code funktioniert, hab ihn zwar grad schon paar mal getestet, aber müsste laufen.

Einfach instanziieren, dann killAll aufrufen und als ersten Parameter einen DisplayObjectContainer übergeben und als zweiten den boolschen wert true or false, je nachdem ob der Container selbst auch entfernt werden soll.
Über den getter killedChildren könnt ihr euch ausserdem noch ausgeben lassen wieviele objekte entfernt wurden.


Viel Spaß damit und greetz,
Bastian


PS: Das package müsst ihr natürlich eurer Struktur nach anpassen...

PHP-Code:
package com.inpose.core.utils
{
    
import flash.display.DisplayObjectContainer;

    public class 
RecursiveDestroyer
    
{
        
        private var 
container             DisplayObjectContainer;
        private var 
startContainer         DisplayObjectContainer;
        private var 
myKilledChildren    uint;
        private var 
killMyself            Boolean false;
        private var 
killedMyself        Boolean false;
        private var 
killer                DisplayObjectContainer;
        
        public function 
RecursiveDestroyer()
        {
            
        }
        
        public function 
get killedChildren () : uint {
            return 
myKilledChildren;
        }
        
        
        public function 
killAll (_startContainer DisplayObjectContainer_killMyself Boolean false) : void {
            
myKilledChildren 0;
            
startContainer _startContainer;
            
killMyself _killMyself;
            
            
startKilling(startContainer);
        }
        
        
        private function 
startKilling(corpse : *) : void {
            
            
            
            if (
corpse is DisplayObjectContainer){
                
                if (
corpse.numChildren 0){
                
                    for (var 
uint corpse.numChildreni--){
                
                        
startKilling(corpse.getChildAt(0));
                
                    }
                }
                
                
                if (
corpse.numChildren == 0) {
                    
                    if (
corpse.parent is DisplayObjectContainer){
                        
                        
killer corpse.parent;
                        
                        try {
                            if (
corpse == startContainer && killMyself) {
                                
killer.removeChild(corpse);
                                
myKilledChildren++;
                                
killedMyself true;
                            }
                            else if (
corpse != startContainer) {
                                
killer.removeChild(corpse);
                                
myKilledChildren++;
                            }
                                
                        }
                        
                        catch (
e:SecurityError) {
                            
trace (e);
                        }
                    }
                    
                }
                
            }
            
            else {
                
killer corpse.parent;
                
killer.removeChild(corpse);
                
myKilledChildren++;
            }
        
            if (
corpse == startContainer && killedMyself) {
                
startContainer null;
                }
        }
        
        
        
    }


Geändert von icymonkey (18-01-2008 um 22:23 Uhr)
icymonkey ist offline   Mit Zitat antworten
Alt 19-01-2008, 07:15   #2 (permalink)
Neuer User
 
Registriert seit: Jul 2003
Beiträge: 30
Naive Frage: Warum muss man alles rekursiv von unten nach oben entfernen? Reicht nicht sowas?:
ActionScript:
  1. public function removeAllChildren(parent:DisplayObjectContainer) : void {
  2.   for (var i : uint = parent.numChildren-1; i >= 0 ; i--) {
  3.     parent.removeChildAt(i);
  4.   }
  5. }
  6.  
  7. // nur kinder entfernen:
  8. removeAllChildren(myContainer);
  9. // alles entfernen:
  10. if (myContainer.parent) myContainer.parent.removeChild(myContainer);
__________________
www.adamtoons.de
adamtoons.de ist offline   Mit Zitat antworten
Alt 19-01-2008, 13:08   #3 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
gute frage ...

bei mir war eben das problem, dass ich teilweise pro DisplayObjectContainer sehr viele children hatte. Und irgendwann hab ich mir mal den Artikel von Grant Skinner über Ressourcemanangement durchgelesen und folglich auch so einen Speicherverbrauch-monitor eingebaut um zu überprüfen ob ich vielleicht vergessen hab irgendwelche variablen freizugeben oder irgendwelche objekte von der bühne zu nehmen weil nach einer zeit das programm immer recht träge wurde. Seit ich nun versuche möglichst alle children von unten nach oben zu entfernen kommt es mir so vor, als würde der garbage collector auch besser arbeiten.

Allerdings würden mich hierzu eure erfahrungen schon sehr interessieren... Reicht es bei euch aus, wenn ihr einfach nur das oberste child von der bühne nehmt und natürlich auch sämtliche referenzen auf dieses child löscht? auch schon mal mit System.gc() getestet?
icymonkey ist offline   Mit Zitat antworten
Alt 19-01-2008, 13:23   #4 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.141
Also, es hängt von der Programmierung ab. Wenn jedes Child einen EventListener Event.ADDED/Event.ADDED_TO_STAGE, Event.REMOVED/Event.REMOVED_FROM_STAGE verpasst bekommt, der dann alle Listener setzt/entfernt, die für Interaktion zuständig sind, sollte es reichen, den Obersten Knoten der (Sub-)DisplayList zu entfernen.
Omega Psi ist offline   Mit Zitat antworten
Alt 19-01-2008, 14:06   #5 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
hmmmm... wär auf jeden fall auch ne gute lösung

allerdings hab ich vor 3 wochen erst mit flash/as3 angefangen und da wusste ich noch nicht mal was events sind... deswegen hab ichs nun mit der rekursion "nachträglich" gelöst. Klappt aber auch ganz gut.


Dennoch würde es mich interessieren, was schneller ist, das durchreichen der events oder das rekursive entfernen. Ich schätz mal fast, die Event-Lösung...

Naja, dann beim nächsten Projekt, aber danke für den Tipp - darauf bin ich noch garnicht gekommen, vor allem dauerts wirklich eine Weile bis man mal versteht wie genau Events funktionieren (ging zumindest mir so).


Gibt es eigentlich irgendeine Möglichkeit, zu testen, wieviel Speicher die einzelnen Klassen zur Laufzeit verbrauchen? Hab mich schon mal umgesehen, aber nichts gefunden. Aber lt. einem Bekannten ist es z.b. bei der .NET umgebung möglich...
icymonkey ist offline   Mit Zitat antworten
Alt 19-01-2008, 14:10   #6 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.141
Ja, die Event-Geschichte ist vor allen Dingen auch etwas schicker. Vor allen Dingen, weil die Events auf jeden Fall dispatch werden, der Mechanismus ist also schon da.

Ich glaube, für das Profiling gibt's was - ich hab aber keinen Link zur Hand.
Omega Psi ist offline   Mit Zitat antworten
Alt 19-01-2008, 14:41   #7 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
Danke, hab mich gerade mal umgesehen... profiling mit flex, allerdings will er grad nicht, weil ich gleich beim start auf fullscreen gehe - selbst wenn ich es auskommentiere bringt er nen fehler... ob ich jetzt diesen allowFullSize in der html reingeschrieben hab weiss ich grad nicht, aber ist auch egal, wenn er meckert selbst wenn ich die zeile rauslösch...

aber noch ne andere frage, nutzt ihr eigentlich die diesen "weak" parameter für eure eventListener? (siehe unten)



// params: eventName, listener, capturePhase, priority, useWeakReference
someObj.addEventListener("eventName",myFunct,false ,0,true);
icymonkey ist offline   Mit Zitat antworten
Alt 19-01-2008, 15:04   #8 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.141
Ja, aber auch noch nicht so lang.

Links:
Omega Psi ist offline   Mit Zitat antworten
Alt 19-01-2008, 15:59   #9 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
Danke, den gskinner link kannte ich schon, die anderen beiden noch nicht.

Wenn ich das richtig verstanden hab, brauche ich bei weak-Listenern diese dann nicht mehr extra zu entfernen über removeListener oder?


eine frage hätte ich allerdings noch - wenn schon mal ein profi zur hand ist :

ich passe die größenverhältnisse in meinem flash über zwei eventListener an, einmal den normalen Resize-event und einmal den FullScreen-Event... allerdings kommt es mir schon seit längerem so vor, als würden diese Events nur in ca 90% der fälle auch richtig gefeuert... gerade eben hab ich noch den render-Event entdeckt... was ist denn sinnvoller? bzw. gibt es gründe sich entweder für resize + fullscreen oder aber NUR render zu entscheiden? oder hab ich da irgendwas falsch gelesen?

Vielen Dank nochmals!


vielleicht doch noch eine weitere frage :

was ist denn der genaue unterschied zwischen REMOVED_FROM_STAGE und REMOVED ? in der Hilfe steht ja folgendes für REMOVED_FROM_STAGE "Dies erfolgt entweder direkt oder über das Entfernen einer Unterstruktur, die das Anzeigeobjekt enthält." ist REMOVED_FROM_STAGE dann eigentlich i.d.r. immer der bessere weg?

Geändert von icymonkey (19-01-2008 um 16:05 Uhr)
icymonkey ist offline   Mit Zitat antworten
Alt 19-01-2008, 16:06   #10 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.141
Ich würde die EventListener trotzdem explizit setzen und entfernen, wenn es der Fall verlangt/ermöglicht. Beispielsweise beim adden und removen von DisplayObjects von der DisplayList. Wenn geadded, dann MouseListener setzen. Wenn ein Event.REMOVED eintriit, MouseListener entfernen. Das ist aber vielleicht auch ein wenig meine art zu programmieren -> explizit.

Genau das ist ein Thema, in dem ich nicht so bewandert bin. Ich würde an deiner Stelle die Events mal einzeln testen und dann versuchen die Resultate zu filtern und auszuwerten.
Omega Psi ist offline   Mit Zitat antworten
Alt 19-01-2008, 19:18   #11 (permalink)
Neuer User
 
Registriert seit: Jul 2003
Beiträge: 30
Zitat:
Zitat von icymonkey Beitrag anzeigen
gute frage ...
Seit ich nun versuche möglichst alle children von unten nach oben zu entfernen kommt es mir so vor, als würde der garbage collector auch besser arbeiten.
Es kann schon sein, das der GC mehr zu tun hat, eine komplexe, abgehängte, aber zusammenhängende display list aufzuräumen. Das wäre dann sowas:
ActionScript:
  1. public function removeAllChildrenRecursive(parent:DisplayObjectContainer) : void {
  2.   for (var i : uint = parent.numChildren-1; i >= 0 ; i--) {
  3.     if (parent.getChildAt(i) is DisplayObjectContainer) {
  4.       removeAllChildrenRecursive(DisplayObjectContainer(parent.getChildAt(i)));
  5.     }
  6.     parent.removeChildAt(i);
  7.   }
  8. }
__________________
www.adamtoons.de
adamtoons.de ist offline   Mit Zitat antworten
Alt 19-01-2008, 19:27   #12 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
sieht auch nett aus - gleich mal ausprobieren... hab nämlich schon gemerkt, dass mein konstrukt ab und zu mal probleme aufwirft


aber mal ne frage:

du hast geschrieben DisplayObjectContainer(parent.getChildAt(i))

ist das dann ein casting oder was passiert hier? mit Konstruktor hats und kanns ja eigentlich nichts zu tun haben???
icymonkey ist offline   Mit Zitat antworten
Alt 19-01-2008, 19:32   #13 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.141
getChildAt liefert nur ein DisplayObject zurück. Du musst überprüfen, ob das child ein DisplayObject ist, und dann casten, sonst kriegst du einen TyeError.
Omega Psi ist offline   Mit Zitat antworten
Alt 19-01-2008, 19:34   #14 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Delmenhorst
Beiträge: 12.141
Geht gerade auch so in die Richtung diese Threads: Link
Omega Psi ist offline   Mit Zitat antworten
Alt 19-01-2008, 19:50   #15 (permalink)
kalt...
 
Registriert seit: Dec 2007
Beiträge: 115
@adamtoons.de :

mir ist nur grad noch aufgefallen, dass du i nicht als uint sondern als int deklarieren musst, sonst bringt der test ob > 0 nicht viel

mal schauen obs so klappt....
icymonkey ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 16:24 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele