44

しばらくの間この問題を検索していました。バックスタックから復元されたフラグメントを特定する方法

フラグメントがバックスタックから復元されていますか? 私は、FragmentActivity内で互換性ライブラリとListFragmentを使用しています。 ListFragment内の項目が選択されると、新しいFragmentが開始され、ListFragmentが置き換えられます。

私は、FragmentActivityが一時停止すると、FragmentのonSaveInstanceStateが呼び出されることに気付きました。しかし、フラグメントがFragmentTransactionを介してバックスタックに置かれると、onSaveInstanceStateは呼び出されず、onCreateViewおよびonActivityCreatedのライフサイクルメソッドがnull savedInstanceState Bundleで呼び出されます。

フラグメントが作成または復元されたときにデータをロードしたいが、ユーザーが戻ったときにデータをロードしたいので、これを求めている。バックスタック。

私はHow to check if Fragment was restored from a backstack? を見てきましたが、これが答えを促すことを希望して詳細を追加したいと思います。

編集: はちょうど

注しかしhttp://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle) が言うに気づい:このメソッドは、onDestroy()の前にいつでも呼び出すことができます。フラグメントが大部分(例えば、UIが表示されていないバックスタックに置かれたときなど)破棄されることが多いが、所有アクティビティが実際にその状態を保存する必要があるまで、その状態は保存されない。

のでonSaveInstanceStateは

+0

この質問にはほとんど更新したように、私はそれが互換ライブラリの癖が原因で、より多くのを疑っています。まだ3.0以上のデバイスでテストケースを実行しようとしていませんでした。 – dvd

+0

'onCreate()'にデータをロードするためにサーバコールを置かないのはなぜですか?おそらく、それはあなたの問題を軽減するでしょう。私はこの特定のメソッドは、フラグメントがバックスタックから復元されたときに呼び出されないと考えています。 – Abhijit

答えて

34

私が最も簡単な方法はonViewCreated()メソッドでは、たとえば、これを行うと思い:、Androidはbackstack上の断片を入れたときに、それだけでそのビューを破棄しますが、インスタンス自体を殺すことはありませんので

if (savedInstanceState == null && !mAlreadyLoaded) { 
    mAlreadyLoaded = true; 

    // Do this code only first time, not after rotation or reuse fragment from backstack 
} 

フラグメントがバックスタックから復元されるとき、mAlreadyLoadedはまだ真です。

+0

フラグメントインスタンスがバックスタックから復元されたかどうかを判断するための正解です。 私は最終的に、このトピックを再訪して、サポートv4ライブラリバージョン13のFragmentManagerへのソースを読みました.ATomのようなフラグメントインスタンスは、バックスタックに追加するときに保持されます。したがって、onViewCreatedのフラグの設定とチェックは機能します。 – dvd

+5

これは 'setRetainInstance(true)'を呼び出した場合にのみ有効です。これは常にオプションではありません。 –

+1

@BenoitDuffez 'FragmentTransaction'がバックスタックに追加されていない' Fragment'で作業している場合にのみ必要です。トランザクションがバックスタックに追加された場合、その 'Fragment'は自動的に保持されます(つまり、' onDestroy'は呼び出されません)。 [** from the docs **](http://developer.android.com/guide/components/fragments.html#Transactions)。それをバックスタックに追加しないと、破壊しないように言ったように 'setRetainInstance()'を呼び出さなければなりません。 –

30
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {  
      public void onBackStackChanged() { 
       Log.i(TAG, "back stack changed "); 
       int backCount = getSupportFragmentManager().getBackStackEntryCount(); 
       if (backCount == 0){ 
            // block where back has been pressed. since backstack is zero. 
       } 
      } 
     }); 

使用...論外間違いなく、このaddOnBackStackChangedListenerです。

+4

私はこれを試しましたが、断片ライフサイクルメソッドが呼び出された後にonBackStackChangedが呼び出されるという問題があります。私がしたいのは、フラグメントが最初に作成されたときにデータをロードし、データを保存し、必要なときにリロードしないで復元することです。これは、onActivityCreatedの条件付きロード/リストアで実現されました。バックスタックをポップしてフラグメントが復元された場合、データをリロードしないでください。 onBackStackChangedにフラグを設定しても、ライフサイクルメソッドはそれを見ません。 – dvd

+0

魅力的な作品です! – portfoliobuilder

+0

question.acceptedAnswer = this; – satheeshwaran

0

isVisibleメソッドを使用すると、最初にフラグメントが表示されるのか、バックスタックから復元されるのかを理解することができます。

8

MAJOR EDIT:アプリケーションがバックグラウンドに入れて戻ってフォアグラウンドになったときに2013年10月15日

(参考のために以下に保持)前の説明は失敗します。

代わりに、バックスタッキングの現在のサイズと、バックスラックに入れた&のフラグメントを作成したときのバックスタックのサイズを比較することをお勧めします。


が、この数字はあなたが断片をbackstackから復元されたとき、そののonCreate()が呼び出されていないことである告げる何http://developer.android.com/guide/components/fragments.html#Creating

で、図2をよく見てくださいそのonCreateViewながら、()です。


だから、あなたはこのような何かやりたいことがあります。あなたはbackstackにフラグメントを追加した場合は

public class MyFragment extends Fragment { 
    int mBackStackSize = 0; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     mBackStackSize = getFragmentManager().getBackStackEntryCount(); 
    } 

    public boolean isRestoredFromBackstack() { 
     return mBackStackSize > getFragmentManager().getBackStackEntryCount(); 
    } 
} 
4

を、そしていくつかの操作をした後、あなたはfragmentTransaction.hide(フラグメント)を使用して、それを隠すし、その後復元それは、fragmentTransaction.show(fragmentManager.findFragmentByTag(fragment.getName()))のようなバックスタックからです。あなたは

@Override 
public void onHiddenChanged(boolean hidden) { 
    // TODO Auto-generated method stub 
    super.onHiddenChanged(hidden); 
    if (!hidden) { 
     //fragment became visible 
     //your code here 
    } 
} 
+0

これはまさに私が探していたものです。ありがとう!ちょうどそれが '( – crubio

0
Fragment.getFragmentManager() == null 

追加前とフラグメントがバックスタックするために呼び出さonDestroyView()を行くとき

12

をポップした後(ブール値は非表示)onHiddenChangedをオーバーライドすることができます。いいえonDestroy()

そして、フラグメントがバックスタックからポップすると、onCreateView()が呼び出されます。いいえonCreate()

ので、断片化し、以下のように従ってboolean mIsRestoredFromBackstackを追加します。

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    mIsRestoredFromBackstack = false; 
} 

@Override 
public void onResume() 
{ 
    super.onResume(); 
    if(mIsRestoredFromBackstack) 
    { 
     // The fragment restored from backstack, do some work here! 
    } 
} 

@Override 
public void onDestroyView() 
{ 
    super.onDestroyView(); 
    mIsRestoredFromBackstack = true; 
} 
+0

)画面をロックすることからonDestroyViewが呼び出されているので、バックスラックから戻った後に私のアクションが2回呼び出されるということに注意してください。 – ldrrp

+1

これは機能します。回答ありがとうございます。 –

関連する問題