2012-04-11 11 views
7

Soy consciente de que las clases internas no se recomiendan en Android porque contienen una referencia a la clase adjunta. Sin embargo, en Java, la clase externa solo se GCed cuando ya no se hace referencia a la clase interna. Eso significa que, en Android, siempre que tenga una referencia no estática en la clase de actividad externa para la clase interna, la clase interna no puede existir más tiempo que la clase de actividad externa porque la actividad solo se puede destruir si no contiene una referencia a la clase interna más (al menos eso es lo que estoy deduciendo). Entonces, ¿cuál es el problema al usar clases internas no estáticas (dado que obviamente no pueden existir más tiempo que la actividad externa si inferimos de Java)? ¿Me estoy perdiendo de algo?Clases internas: Android vs Java

Gracias!

+1

¿Dónde se lee clases internas no estáticos no se recomiendan en Android? – Cristian

+0

Esto no es solo un problema de Android. Para el código intercambiable y rápido, debe evitarlos, excepto que son estáticos y almacenan la información que requieren como campos locales. El problema con las clases internas es que no puede establecer la referencia a la clase padre a 'null' para obtener el valor GC. El compilador debe generar métodos de acceso si los miembros de la clase padre que el acceso a la clase interna son privados y usted tiene una clase interna por instancia de clase principal. – Stephan

+0

@Cristian desplácese hasta la parte inferior de este enlace http://developer.android.com/resources/articles/avoiding-memory-leaks.html debe evitarse si no puede controlar el ciclo de vida de la clase interna. – OckhamsRazor

Respuesta

8

consideran este sencillo ejemplo

class Leaker 
{ 
    public static Object leakedObj; 
} 

class MyActivity extends Activity 
{ 
    public class MyInnerClass { ... } 

    void onCreate(Bundle savedState) 
    { 
     Leaker.leakedObj = new MyInnerClass(); 
     //The activity now won't be GCed until Leaker.leakedObj is cleared.   
    } 
} 

Puede pasar fácilmente de una clase no estática interna fuera del contexto de su actividad. Siempre y cuando no pases tu clase interna a objetos fuera del ciclo de vida de tu actividad, deberías estar bien. Pero ciertamente es posible filtrar su actividad a través de una clase interna.

+0

gracias justin. tu respuesta parece prometedora tan solo para confirmar: ¿las clases internas no estáticas pueden vivir más que una actividad si no hay otras referencias a la clase interna, excepto las referencias en la actividad externa solamente, todas las cuales no son estáticas? – OckhamsRazor

+0

+1 para señalar el problema principal con clases internas no estáticas de actividad: una actividad no puede ser GC en el momento deseado porque un tercer objeto vivo (ciclo de actividad no activo) en otro lugar está aferrado a una referencia a una instancia de la clase interna, que a su vez se cuelga de la Actividad a través de una referencia sintética. –

+0

@OckhamsRazor, si las únicas referencias a su clase interna provienen de la Actividad (y todas son no estáticas), entonces la Actividad se recopilará normalmente. –

6

No me molestaré en parafrasear, porque Google puede explicarlo mejor.

Suponiendo: Clase de los padres es Foo y clase interna es Foo$Inner:

El problema es que la máquina virtual considera que el acceso directo a los miembros privados de Foo de Foo $ Interno ser ilegal porque Foo y Foo $ Interior distintas clases, aunque el lenguaje Java permite que una clase interna acceda a miembros privados de una clase externa. Para cerrar la brecha, el compilador genera un par de métodos sintéticos:

/*package*/ static int Foo.access$100(Foo foo) { 
    return foo.mValue; 
} 
/*package*/ static void Foo.access$200(Foo foo, int value) { 
    foo.doStuff(value); 
} 

El código de clase interna llama a estos métodos estáticos cada vez que necesita para acceder al campo mvalue o invocar el método hacerTarea en la clase externa. Lo que esto significa es que el código anterior realmente se reduce a un caso en el que está accediendo a los campos de miembros a través de métodos de acceso. Anteriormente hablamos sobre cómo los accessors son más lentos que los accesos directos a los campos, por lo que este es un ejemplo de un idioma determinado que resulta en un golpe de desempeño "invisible".

Si está utilizando un código como este en un punto de acceso de alto rendimiento, puede evitar la sobrecarga declarando campos y métodos a los que acceden las clases internas para tener acceso a paquetes, en lugar de acceso privado. Desafortunadamente, esto significa que se puede acceder directamente a los campos por otras clases en el mismo paquete, por lo que no debe usar esto en la API pública.

Fuente: https://developer.android.com/training/articles/perf-tips.html#PackageInner

+0

gracias, esto es genial. pero todavía no responde a mi pregunta: ¿pueden las clases internas no estáticas vivir más tiempo que una actividad si no hay otras referencias a la clase interna a excepción de las referencias en la actividad externa, que no son estáticas? – OckhamsRazor

+0

@OckhamsRazor Pregunta "¿Pueden [instancias de] clases internas no estáticas vivir más tiempo que una actividad si no hay otras referencias a [instancias de] la clase interna a excepción de referencias [no estáticas] en la actividad externa?" La respuesta es no. –

+0

ah, genial, gracias Mike, lo expresaste mejor. y también eso es lo que quería saber. ¡aclamaciones! – OckhamsRazor

Cuestiones relacionadas