2009-04-02 25 views
20

Quiero eliminar/forzar la recolección de elementos no utilizados en una instancia de clase desde su interior. Obviamente, this = null y delete this no funcionan. ¿De alguna manera puedo hacer eso, o estoy ladrando el árbol equivocado? Básicamente estoy buscando un destructor de algún tipo ...¿cómo elimino/gc un objeto en Actionscript 3?

Tengo una instancia de clase que intenta cargar un archivo XML, y si el archivo no se encuentra, quiero destruir la instancia, preferiblemente desde adentro. El punto es hacer algunas cosas en la clase principal dependiendo de si la instancia hija es nula o no.

He pensado en lanzar un evento al padre y eliminarlo de allí, pero preferiría hacerlo solo si no hubiera otra forma.

Respuesta

22

No debe intentar quitar el objeto de sí mismo; es una mala práctica, y en AS3 no puede hacerlo con seguridad.

se puede eliminar (es decir, la recolección de basura) solo si no hay referencias restantes para ese objeto. Como las referencias siempre pasan por valor y el objeto generalmente no tiene conocimiento de las referencias que existen, no puede eliminar el objeto de sí mismo. Lo único útil que puede hacer es crear un método que borre todos los recursos utilizados por una instancia. Tal método servirá como un destructor, pero tendrá que llamarlo manualmente. No olvides que los oyentes de eventos también evitarán la recolección de basura a menos que los elimines.

También hay una diferencia entre delete 'en una propiedad y configurándola en null. Efectivamente, delete eliminará una propiedad de una instancia de clase dinámica. Mientras que establecer el valor de la propiedad en null no eliminará la propiedad, pero borrará cualquier referencia que haya almacenada allí. Por lo tanto, ambas acciones destruirán la referencia que se almacenó en alguna propiedad. Tenga en cuenta que no puede delete un objeto, solo una propiedad.

Existen ciertos hacks que se pueden utilizar para iniciar la recolección de basura en reproductores flash de 9 y más años. Sin embargo, recientemente, la llamada System.gc() estuvo disponible, lo cual hace lo mismo. Tenga en cuenta que realmente no puede confiar en el hecho de que en realidad se llamará a GC. Esto depende del reproductor flash.

Volviendo a su pregunta: lanzando el evento y notificando a los padres que algo salió mal, en realidad es una buena idea. Debes apegarte a eso. Además, es mejor si el padre sabrá de tal evento de esa manera, y no cuando descubrirá que algunas propiedades se anularon mágicamente.

P.S .: Reading Grant Skinner articles on memory en flash player es en realidad una buena idea.

+0

"Tenga en cuenta que no puede eliminar un objeto, solo una propiedad". - No estoy seguro de lo que quieres decir con esto. ¿Qué pasa si mi propiedad es un objeto? – Luke

+2

@Luke: me refiero a que la propiedad del objeto A puede contener una referencia a algún objeto B, pero 'delete A.prop' solo eliminará esa propiedad, junto con una referencia. Es decir. A ya no tendrá propiedad 'prop', pero probablemente haya referencias al objeto B dejado en alguna parte. Entonces B no recibirá GC. – dragonfly

+6

'System.gc()' solo está disponible para versiones de depuración de flash player. Debe revisar para mencionar que no debe usarse para otra cosa que no sea la depuración. –

1

AS3 no le da ningún destructor. Lo mejor que puede hacer es establecer todas las referencias al null y mantener los dedos cruzados, que el GC lo notará y liberará la memoria.

+0

Bien, pero ¿cómo configuro una instancia de clase nula desde dentro? – evilpenguin

+0

@evilpenguin, a menos que esté utilizando un singleton, no lo hace desde el interior de la clase. Lo haces desde la clase que ha instanciado esa clase. – KingNestor

+0

@evilpenguin: Como se sugiere, debes hacerlo desde afuera. – dirkgently

1

Usted debe tener una lectura acerca de la recolección de basura en primer lugar, Grant.S escribió un buen artículo sobre esto:

http://www.gskinner.com/blog/archives/2006/06/as3_resource_ma.html

El punto no es establecer la clase en sí misma para anular, sino eliminar todas sus referencias, incluidos los oyentes. Una vez que está completamente huérfano, la basura puede recogerlo en un punto.

Ejemplo básico:

// References a newly created sprite 
var reference:Sprite = new Sprite(); 

// Removes the reference, the Sprite is now orphaned and will probably be garbage collected within some seconds. 
reference = null; 

Una buena práctica es crear un método sistemático 'destruir' en todas sus clases que elimina todas sus referencias internas, dispone de mapas de bits, elimina los detectores de eventos, etc., a partir de entonces se solo tendrá que preocuparse por desvincular los externos.

Si usa FLEX Builder, puede usar el generador de perfiles para visualizar la forma en que Flash Player maneja todo esto internamente.

1

Aquí hay una forma no admitida de forzar la recolección de basura desde GSkinner.

try { 
    new LocalConnection().connect('foo'); 
    new LocalConnection().connect('foo'); 
} catch (e:*) {} 
// the GC will perform a full mark/sweep on the second call. 
5

Si el objeto se añadió a una DisplayContainer utilizando el método addChild(), se puede extraer el objeto del recipiente desde dentro del objeto, mediante el uso de parent.removeChild (esto). Si no hay referencias al objeto que queda después de eso, será recogido por el recolector de basura.

El único problema es cuando tiene detectores de eventos dentro del objeto, que puede eliminar manualmente o dejar que el recolector de elementos no utilizados lo haga estableciendo weakReference = true en todos los oyentes.

Cuestiones relacionadas