2012-04-11 18 views
7

Sono consapevole che le classi interne non sono consigliate in Android perché contengono un riferimento alla classe che le include. Tuttavia, in Java, la classe esterna è solo GCed quando la classe interna non viene più referenziata. Ciò significa che, in Android, purché tu abbia un riferimento non statico nella classe di attività esterna alla classe interna, la classe interna non può esistere più a lungo della classe di attività esterna perché l'attività può essere distrutta solo se non contiene un riferimento alla classe interiore (almeno questo è quello che sto dicendo). Quindi qual è il problema usando le classi interne non statiche (dato che non possono ovviamente esistere più a lungo dell'attività esterna se si deduce da java)? Mi sto perdendo qualcosa?Classi interne: Android vs Java

Grazie!

+1

Dove l'hai letto le classi interne non statici non sono raccomandati in Android? – Cristian

+0

Questo non è solo un problema di Android. Per il codice intercambiabile e veloce, è necessario evitarli, ad eccezione del fatto che sono statici e memorizzano le informazioni richieste come campi locali. Il problema con le classi interne è che non è possibile impostare il riferimento alla classe genitore su 'null' per ottenerlo. Il compilatore deve generare metodi di accesso se i membri della classe genitore che l'accesso alla classe interna sono privati ​​e si ha una classe interna per ogni istanza della classe genitore. – Stephan

+0

@Cristian scorrere fino alla fine di questo link http://developer.android.com/resources/articles/avoiding-memory-leaks.html da evitare se non è possibile controllare il ciclo di vita della classe interna. – OckhamsRazor

risposta

8

Considerate questo semplice esempio

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.   
    } 
} 

Si può facilmente passare una classe non statica interna di fuori del contesto della vostra attività. Finché non passi la tua classe interiore a oggetti al di fuori del ciclo di vita dell'Attività, dovresti stare bene. Ma è certamente possibile divulgare la tua attività attraverso una classe interiore.

+0

grazie justin. la tua risposta sembra promettente. quindi, solo per confermare, le classi interne non statiche possono vivere più a lungo di un'attività se non ci sono altri riferimenti alla classe interna eccetto per i riferimenti nell'attività esterna, che sono tutti non statici? – OckhamsRazor

+0

+1 per evidenziare il problema principale con le classi interne non statiche di attività: un'attività può non essere GC nel momento desiderato perché un terzo oggetto live (non-Activity-lifecycle) da qualche altra parte è sospeso a un riferimento a un'istanza della classe interiore, che a sua volta si blocca sull'Attività tramite riferimento sintetico. –

+0

@OckhamsRazor, Se gli unici riferimenti alla classe interna provengono dall'attività (e sono tutti non statici), l'attività verrà raccolta normalmente. –

6

Non mi preoccuperò di parafrasare, perché Google può spiegarlo meglio.

Supponendo: classe padre è Foo e classe interna è Foo$Inner:

Il problema è che la VM considera l'accesso diretto ai membri privati ​​di Foo da Foo $ interno di essere illegale perché Foo e Foo $ interno sono diverse classi, anche se il linguaggio Java consente ad una classe interna di accedere ai membri privati ​​di una classe esterna. Per colmare il gap, il compilatore genera un paio di metodi sintetici:

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

Il codice classe interna richiama questi metodi statici ogni volta che deve accedere al campo Lvalore o richiamare il metodo doStuff nella classe esterna. Ciò significa che il codice sopra riportato si riduce a un caso in cui si sta accedendo ai campi membri tramite metodi di accesso. In precedenza abbiamo parlato di come gli accessor sono più lenti degli accessi diretti al campo, quindi questo è un esempio di un determinato linguaggio che ha come risultato un hit "invisibile".

Se si utilizza un codice come questo in un hotspot di prestazioni, è possibile evitare il sovraccarico dichiarando campi e metodi a cui le classi interne accedono per avere accesso al pacchetto, piuttosto che accesso privato. Sfortunatamente questo significa che i campi possono essere richiamati direttamente da altre classi nello stesso pacchetto, quindi non dovresti usarlo nelle API pubbliche.

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

+0

grazie, questa è roba interessante. ma non risponde ancora alla mia domanda: le classi interne non statiche possono vivere più a lungo di un'attività se non ci sono altri riferimenti alla classe interiore eccetto per i riferimenti nell'attività esterna, che sono non statici? – OckhamsRazor

+0

@OckhamsRazor Si chiede "le [istanze di] classi interne non statiche vivono più a lungo di un'attività se non ci sono altri riferimenti a [istanze di] la classe interna eccetto per i riferimenti [non statici] nell'attività esterna?" La risposta è no. –

+0

ah, bello, grazie, mi hai detto meglio. e anche questo è quello che volevo sapere. Saluti! – OckhamsRazor

Problemi correlati