2014-10-07 1 views
6

ich den Artikel "Avoiding memory leaks" gefunden, wo gesagt wird, dass der folgende Code:Legendes Speicherlecks in Android-Anwendung

private static Drawable sBackground; 

@Override 
protected void onCreate(Bundle state) { 
    super.onCreate(state); 

    TextView label = new TextView(this); 
    label.setText("Leaks are bad"); 

    if (sBackground == null) { 
    sBackground = getDrawable(R.drawable.large_bitmap); 
    } 
    label.setBackgroundDrawable(sBackground); 

    setContentView(label); 
} 

ist keine gute Idee, da:

Wenn die Bildschirmausrichtung ändert Das System wird standardmäßig die aktuelle Aktivität zerstören und eine neue erstellen, während der Status beibehalten wird. Auf diese Weise lädt Android die Benutzeroberfläche der Anwendung von den Ressourcen neu.

So ist der obige Code:

... leckt die erste auf der ersten Änderung der Bildschirmausrichtung erstellt Aktivität. Wenn ein Drawable an eine Ansicht angehängt ist, wird die Ansicht als Rückruf für das Zeichenfeld festgelegt. Im Codeausschnitt oben, diese bedeutet die ziehbar einen Verweis auf die Textview hat, die selbst einen Bezug auf die Aktivität hat (der Kontext), die abwechselnd Referenzen auf so ziemlich alles hat (abhängig von Ihrem Code.)

Aber, wenn die Bildschirmausrichtung ändert, wird die Methode setBackgroundDrawable(Drawable background) genannt wird, die wiederum ruft:

background.setCallback(this); 

das Verfahren Drawable.setCallback() wird in der folgenden Art und Weise definiertem:

public final void setCallback(Callback cb) { 
    mCallback = new WeakReference<Callback>(cb); 
} 

So sollte jetzt Hintergrund den alten Verweis auf den vorherigen TextView freigeben, und ein neuer Verweis auf den neuen TextView sollte erstellt werden.

Es scheint also so, als ob die Änderung der Bildschirmausrichtung nur eine Referenz verliert, bis die Aktivität neu erstellt wird.

Wohin gehe ich falsch?

+2

Zusätzlich zu der richtigen Antwort, wenn Sie eine Static in einer Aktivität sehen, sollten Sie sich instinktiv unwohl fühlen (siehe 'code smells') und' this', 'Context' oder irgendetwas anderes, das eine' Activity' betrifft, an eine Objekt Sie können nicht direkt die Lebensdauer von und ** garantieren **, dass es höchstens so lange wie die "Aktivität", sollten Sie auf der Stelle zu erbrechen. – Simon

+0

Ja, klar. Danke @Simon – GVillani82

+0

Romain Guy erklärt die Szenarien für das Speicherleck in den Kommentaren zum ursprünglichen [Blogpost] (http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on) -Android/). – corsair992

Antwort

11

Sie haben absolut Recht. Es gibt jedoch einen subtilen Punkt: Der Artikel ist von . Damals war die Umsetzung der setCallbackdifferent:

Android < = 2.3.7:

public final void setCallback(Callback cb) { 
    mCallback = cb; 
} 

Android> = 4.0.1:

public final void setCallback(Callback cb) { 
    mCallback = new WeakReference<Callback>(cb); 
} 

Grepcode zeigt keine Quellcode von Zwischenversionen, dies ist der einzige Unterschied, den ich schnell finden konnte.


Also, noch einmal, du bist absolut richtig in diesem speziellen Fall (wenn Sie> 14 peilen das ist). Es ist jedoch immer noch sehr wichtig, wirklich darüber nachzudenken, was tatsächlich passiert, wenn Sie eine statische Referenz auf solche Objekte behalten (wie Sie es getan haben). Es gibt zahlreiche Fälle, in denen Sie sicherlich die Context verlieren könnten.

+0

genau was ich überprüft habe – njzk2

+2

Sie haben Recht! Danke für die Antwort – GVillani82