2013-03-05 44 views
2

im想知道androids垃圾收集器如何處理片段保留的數據(保留實例)。Android:片段保留實例內存管理

如果我有一類hirarchy這樣的:

class MyFragment extends Fragment { 

     private DataManager dataManager; 

     public MyFragment(){ 
      setRetainInstance(true); 
     } 


     public void onCreate(){ 
      if (dataManager == null) 
      dataManager = new DataManager(); 

      dataManager.setView(this); 
     } 


     public void onCreateView(){ 
      // display the data of the dataManager 
     } 


     public void onStop(){ 
      dataManager.setView(null); 
     } 
    } 


class DataManager implements DataChangedListener { 

    private MyFragment view; 
    private Data data; 


    public DataManager(){ 

      data.setDataChangedListener(this); 

    } 


    public void setView(MyFragment v){ 
      this.view = v;   
     } 

} 


class Data { 

     public void setDataChangedListener(DataChangedListener l){ 
      this.listener = l; 
     } 
} 

所以我想要做的是,在orientation變化的片段觀看的內容將被recreatd。但底層數據(DataManager和Data)不能重新加載。 DataManager監聽數據對象的更改,將會將此更改轉發到UI,即FragmentFragment在「重新」創建時「附加」到DataManager

到目前爲止這麼好。在我看來,這是一個很好的解決方案,結構良好。基本上它是某種模型 - 視圖 - 演示者模式。

但現在我想知道,當Android將運行垃圾收集器來收集DataManager和數據對象。

假設我有一個活動,顯示MyFragment

但是當應用程序的用戶導航到另一個活動時,內存會發生什麼變化,從而顯示完全不同的內容。

由於DataManager有一個參考數據,反之亦然,我猜數據將被永久地保存在內存中,對吧? 所以我猜垃圾收集器只會在設備進入低內存的時候刪除它。但我想,這兩個對象不會自動成爲垃圾收集的前兩個數據對象。我猜有一種「內存死鎖」。

您認爲如何?有什麼建議麼?

+0

爲了避免這種泄漏,您可以使用WeakReference:http://weblogs.java.net/blog/2006/05/04/understanding-weak-references – 2013-03-05 09:34:50

回答

0

關於垃圾收集器:

我可能會在一些概念在這裏是錯誤,但據我所知,垃圾收集器從已知對象開始和「導航」下的對象樹,如果有任何目標不在那棵樹上,它會被收集。

例如,它從活動中統計出來,並且它引用了幾個視圖,一個適配器和FragmentManger,FragmentManager引用了3個片段,這些片段引用了一些數據對象等等上。

但是,如果Object_A將Object_B和Object_B引用到Object_A但沒有其他人引用Object_A或Object_B,那麼您可以親吻再見那兩位。

建議:

平時要簡化整個setRetainInstance(true);交易,我爲我自己的規則(請記住,這不是強制性的,但它確實使生活更容易理解和抽象):如果我想/需要保留數據並使用setRetainInstance表示一個片段沒有視圖。這意味着,我不會覆蓋它的onCreateView和它的交易這是一個簡單的add(mFrag, MyFrag.TAG);,而不是放置在佈局的任何地方。

這簡化了,因爲你知道,在需要的時候所有的意見都重新創建你可以隨時訪問使用getFragmentManager().findFragmentByTag(MyFrag.TAG);

再回到GC交易數據,用這種方法你知道你的數據不會被GCed,因爲它由FragmentManager安全地保存。

聽起來像一個很好的計劃?你怎麼看?

編輯:

進一步建議:

不要在你的DataFragment參考任何視圖或活動,或上下文。任何長時間的活體都不應該保留這些引用,因爲它們會保持整個活動,這是一個巨大的內存泄漏。

+0

謝謝!我添加了一些更多的代碼給我的分片代碼。我想要做的是在不丟失/重新加載數據的情況下處理方向更改。但是當我完成活動時,例如通過開始另一項活動,我想確保數據可以由GC收集。所以,當我離開包含片段的Activity時,DataManager和Data之間有引用。沒有其他參考。這就像你上面描述的,你猜它可以被GCed。你確定嗎,還是猜測?關於你如何處理setRetainInstance()的一句話,我不明白。你能解釋一下嗎? – sockeqwe 2013-03-07 21:01:29

+0

在\\ sdk \ extras \ android \ support \ samples \ Support4Demos \ src \ com \ example \ android \ supportv4 \ app \ FragmentRetainInstanceSupport.Java上檢查您的示例。那是我的意思。檢查可以工作的片段,並保存數據沒有「onCreateView」 – Budius 2013-03-07 21:55:06