2

im wondering how androids garbage collector works with data that is kept by the fragment (retain instance).

If I have a Class hirarchy like this:

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

So what i want to do is, that on orientation change the fragments view content will be recreatd. But the underlying data (DataManager and Data) must not reload. The DataManager listen to the Data Object for changes, an will forward this changes to the UI, the Fragment. Fragment is "attached" to the DataManager when its (re)created.

So far so good. It seems to me a good Solution and well structured. Basically its some kind of Model-View-Presenter pattern.

But now im wondering, when Android will run the garbage collector to collect the DataManager and Data Objects.

Assume I have an Activity that displays MyFragment.

But what happens to the memory, when the user of the App navigates to another Activity, that displays something completely different.

Since there is a reference from DataManager to Data and vice versa, I guess that the data will be kept "forever" in memory, right? So I guess the garbage collector will only remove this both when the device is going on low memory. But I guess, that these two objects would not be automatically the first two data objects that were garbage collected. I guess there is some kind of "memory deadlock".

What do you think? Any suggestions?

4

1 に答える 1

0

ガベージコレクターについて:

ここでいくつかの概念が間違っている可能性がありますが、私の知る限り、ガベージコレクターは既知のオブジェクトから開始し、オブジェクトツリーを「ナビゲート」します。オブジェクトがそのツリーにない場合は、収集されます。

たとえば、アクティビティから統計を取得し、いくつかのビュー、アダプター、および FragmentManger への参照を持ち、FragmentManager には 3 つのフラグメントへの参照があり、それらのフラグメントはいくつかのデータ オブジェクトへの参照などがあります。

しかし、Object_A が Object_B を参照し、Object_B が Object_A を参照しているが、Object_A または Object_B を参照しているユーザーが他にいない場合は、これら 2 つに別れを告げることができます。

提案:

通常、取引全体を単純化するsetRetainInstance(true);ために、私は自分自身でルールを作成します (これは必須ではありませんが、理解しやすく、抽象化が容易になります): データを保持したい/保持する必要がありsetRetainInstance、1 つのフラグメントにないビュー。つまり、私はそれをオーバーライドせずonCreateView、トランザクションは単純add(mFrag, MyFrag.TAG);であり、レイアウトのどこにも配置しません。

必要に応じてすべてのビューが再作成され、次を使用していつでもデータにアクセスできることがわかっているため、これは簡素化されます。getFragmentManager().findFragmentByTag(MyFrag.TAG);

GC の話に戻りますが、このアプローチでは、FragmentManager によってデータが安全に保持されるため、データが GC されないことがわかります。

良い計画のように聞こえますか?あなたはどう思いますか?

編集:

さらなる提案:

DataFragment 内のビュー、アクティビティ、またはコンテキストへの参照を保持しないでください。アクティビティ全体を保持しているため、長寿命のオブジェクトはこれらの参照を保持しないでください。これは巨大なメモリリークです。

于 2013-03-05T09:39:12.837 に答える