12

フラグメントに関する非常に奇妙な問題があります。私は最新のサポートライブラリを使用しています。私もGoogleと同じコードを使用していますIOSCHED projectAndroid:サポートフラグメンテーションマネージャを使用した場合のフラグメントの複製

しかし、私は回転後の活動の再作成に問題があります。アクティビティが破棄され、再び作成された後、(onStartメソッドで)フラグメントトランザクションを管理するためのメソッドを呼び出します。この行は1回だけ呼び出されますが、フラグメントTWICE!が作成されます。

public abstract class SinglePaneActivity extends FragmentActivity 
{ 
    @Override 
    protected void onStart() 
    { 
     super.onStart(); 

     if(mFragment == null) 
     { 
      mFragment = onCreatePane();  
      mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

      Log.w(TAG, "Fragment creation counter = " + createCounter); 
      createCounter++; 

      getSupportFragmentManager() 
      .beginTransaction() 
      .add(R.id.root_container,mFragment) 
      .commit(); 
     } 
    } 

    @Override 
    protected void onStop() 
    { 
     Log.i(TAG, "onStop"); 
     if(mFragment != null) 
     { 
      getSupportFragmentManager() 
      .beginTransaction() 
      .remove(mFragment) 
      .commit(); 

      mFragment = null; 
     } 
     super.onStop(); 
    } 
} 

と私のログ:

これが私の活動の方法である

--Start of application-- 
11-18 13:26:37.050: I/SinglePaneActivity(19040): onCreate 
11-18 13:26:37.050: I/SinglePaneActivity(19040): onStart 
11-18 13:26:37.055: W/SinglePaneActivity(19040): replacing fragment, counter = 1 
11-18 13:26:37.075: I/MyFragment(19040): onCreate 
11-18 13:26:37.110: I/MyFragment(19040): onActivityCreated 
--Rotating the device-- 
11-18 13:26:39.600: I/SinglePaneActivity(19040): onStop 
11-18 13:26:39.600: I/SinglePaneActivity(19040): onDestroy 
11-18 13:26:39.605: I/MyFragment(19040): onDestroy 
11-18 13:26:39.755: I/MyFragment(19040): onCreate 
11-18 13:26:39.755: I/SinglePaneActivity(19040): onCreate 
11-18 13:26:39.790: I/MyFragment(19040): onActivityCreated 
11-18 13:26:39.800: I/SinglePaneActivity(19040): onStart 
11-18 13:26:39.800: W/SinglePaneActivity(19040): replacing fragment, counter = 2 
11-18 13:26:39.810: I/MyFragment(19040): onCreate 
11-18 13:26:39.815: I/MyFragment(19040): onActivityCreated 
--Rotating the device back-- 
11-18 13:36:47.060: I/SinglePaneActivity(19040): onStop 
11-18 13:36:47.060: I/SinglePaneActivity(19040): onDestroy 
11-18 13:36:47.060: I/MyFragment(19040): onDestroy 
11-18 13:36:47.065: I/MyFragment(19040): onDestroy 
11-18 13:36:47.130: I/MyFragment(19040): onCreate 
11-18 13:36:47.130: I/MyFragment(19040): onCreate 
11-18 13:36:47.130: I/SinglePaneActivity(19040): onCreate 
11-18 13:36:47.140: I/MyFragment(19040): onActivityCreated 
11-18 13:36:47.150: I/MyFragment(19040): onActivityCreated 
11-18 13:36:47.150: I/SinglePaneActivity(19040): onStart 
11-18 13:36:47.150: W/SinglePaneActivity(19040): replacing fragment, counter = 3 
11-18 13:36:47.160: I/MyFragment(19040): onCreate 
11-18 13:36:47.160: I/MyFragment(19040): onActivityCreated 
--Exiting the app-- 
11-18 13:36:48.880: I/SinglePaneActivity(19040): onStop 
11-18 13:36:48.885: I/SinglePaneActivity(19040): onDestroy 
11-18 13:36:48.885: I/MyFragment(19040): onDestroy 
11-18 13:36:48.890: I/MyFragment(19040): onDestroy 
11-18 13:36:48.890: I/MyFragment(19040): onDestroy 

ので、断片の数は、各回転の後に成長しています。

ローテーション後、フラグメントが復元されてからonStartメソッドが実行され、onStartメソッドによって同じフレームレイアウトコンテナに2番目の同じフラグメントが作成されます。しかし、それはどこで最初の断片を復元するのですか?私はそれを捨てたい。または、すでに作成されているかどうかテストするために「if」を変更する必要がありますか?しかし、私はそれを決定する方法を知らない。ヌルテストは役に立たないと思われます。

また、add()の方法をreplace()に置き換えて、小さな回避策を講じました。その後、断片の数は増えておらず、新しい断片がonStartメソッドが作成される前に破棄されます。しかし、これはいくつかの断片で重大な問題を引き起こします。私はいくつかのバックグラウンドプロセスをoncreateメソッドで開始します...

どうすればいいですか?アドバイスやアイデアをありがとうございました!

答えて

23

私は解決策を見つけました。フラグメントマネージャーを使ってコードをonStartからonCreateに移動し、nullの値がsavedInstanceStateであることを確認しなければなりませんでした。まあ、私はそれが保存され、自動的にsavedInstanceStateから復元されたことを知らなかった。知っておいてよかった!

EDIT: 、完全に正しいことを行うには、つまりはsavedInstanceStateがnullでないとき、そこにあるべきフラグメントを復元:

if(savedInstanceState == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     getSupportFragmentManager() 
     .beginTransaction() 
     .add(R.id.root_container,mFragment) 
     .commit(); 
    } 
    else 
    { 
     mFragment = getSupportFragmentManager().findFragmentById(R.id.root_container); 
    } 
+0

はい!ありがとうございました。私は同じ問題で苦労していた。私のフラグメントをロードする前に、私のアクティビティでnull savedInstanceStateがチェックされていました。トリックは – Chiatar

-1

またはあなたのフラグメントがバックスタックにない場合は、次のsetRetainInstance(true);

+1

でした。これはお勧めしません。フラグメントがアクティビティのインスタンスへの参照を保持している場合直接またはビューなどのメンバを介してアクセスすると、メモリリークが発生します。 – frostymarvelous

1

私も同様の問題がありましたが、親フラグメントから子フラグメントを追加して、重複子フラグメントを見ていました。親フラグメントのonStartに追加しようとしていたので、親ビューにアクセスできました。これはonCreateで利用できません。コードをonCreateに移動する代わりに、onActivityCreatedに移動しました。そのメソッドは親ビューへのアクセス権を持ち、フラグメントがすでに自動的に追加されているかどうかを確認するために変数savedInstanceStateにもアクセスできます。これはアクティビティのビューがonCreateで利用可能であるため、アクティビティからフラグメントを追加するときには問題ありません。何らかの理由であなたがonStartまたはsavedInstanceStateが利用できない別の場所にフラグメントを追加する必要がある場合


は、ここで代替です。質問の元のオンスタートコードを使用する...

...あなたはreplaceいうよりaddフラグメントができますフラグメントがすでに自動的に追加された場合

if(mFragment == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     Log.w(TAG, "Fragment creation counter = " + createCounter); 
     createCounter++; 
    } 

    getSupportFragmentManager() 
    .beginTransaction() 
    .replace(R.id.root_container,mFragment) 
    .commit(); 

はその後、あなたの新しいフラグメントは、ちょうどビューで置き換えられます。

関連する問題