2014-10-07 160 views
6

我發現文中的"Avoiding memory leaks",它是說下面的代碼:瞭解內存泄漏

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); 
} 

是不是一個好主意,因爲:

當屏幕方向變化默認情況下,系統將銷燬當前活動並創建一個新的活動,同時保留其狀態 。這樣做,Android將從 資源中重新加載應用程序的用戶界面。

所以上面的代碼:

...泄漏在第一屏幕方向變化所造成的第一個活動。將Drawable附加到視圖時,將視圖 設置爲drawable上的回調。在上面的代碼段,這 意味着繪製有TextView的引用,其本身具有 參考活動(上下文),這反過來有引用 到幾乎任何東西(取決於你的代碼。)

但是,當屏幕方向的變化,該方法setBackgroundDrawable(Drawable background)被調用,進而調用:

background.setCallback(this); 

的方法Drawable.setCallback()以下列方式爲definied:

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

所以,現在背景應該釋放舊的引用到以前的TextView,並且應該創建對新的TextView的新引用。

因此,好像更改屏幕方向會泄漏參考,直到新創建活動爲止。

我哪裏錯了?

+2

除了正確的答案之外,在活動中看到一個靜態應該會讓你本能地感到不適(參見'code smells')並將'this',或者'Context'或其他引用一個Activity的東西傳遞給對象,你不能直接控制它的生命週期,並且**保證**,至多,只要'活動',應該讓你在現場嘔吐。 – Simon 2014-10-07 20:39:19

+0

是的,清楚。謝謝@Simon – GVillani82 2014-10-07 20:44:22

+0

Romain Guy在原始[博客文章](http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on)的評論中解釋了內存泄漏的場景-Android /)。 – corsair992 2014-10-07 21:42:22

回答

11

你是對的。然而,有一個微妙的一點:該文章是從。那時,的setCallback的實施是different

的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沒有顯示出中間版本的源代碼,這是我可以快速找到的唯一區別。


所以,再一次,你在這個特定的情況下,絕對正確(如果你的目標> 14即是)。然而,當你保持對這些項目的靜態引用時(像你所做的那樣),真正思考實際發生的事情仍然非常重要。有很多情況下你肯定可能會泄漏Context

+0

正是我正在檢查 – njzk2 2014-10-07 20:36:04

+2

你是對的!謝謝你的答案 – GVillani82 2014-10-07 20:39:07