9

子ViewPagerを含むViewPagerを持つ親のFragmentアクティビティがあります。子ViewPagerには、各ページのフラグメントが含まれています。私はこれらの子ページフラグメントとトップの親フラグメントアクティビティとの間で、コールバックインターフェースを使用して通信します。親フラグメント活動にアクティビティの再起動後に 'getSupportFragmentManager()'が呼び出されたときに 'IllegalStateException:アクティビティが破棄されました'

public interface Callbacks { 
    public void onItemSelected(Link link); 
} 

私はonItemSelectedイベントをリッスン例えば

@Override 
public void onItemSelected(Link link) { 
    Bundle argumentsFront = new Bundle(); 
    argumentsFront.putParcelable(FragmentComments.ARG_ITEM_ID, link); 
    fragmentComments = new FragmentComments(); 
    fragmentComments.setArguments(argumentsFront); 
    getSupportFragmentManager().beginTransaction().replace(R.id.post_container, fragmentComments).commitAllowingStateLoss(); 
} 

これは、アプリが初めて起動されたときに正常に機能します。

方向を変更するようにデバイスをオンにすると、アクティビティが再開します。 setRetainInstance(true);を使用すると、すべてのフラグメントが再初期化されます(子ViewPagerのフラグメントではsetRetainInstance(true)はサポートされていないため呼び出さない)。私は子供ViewPagerの断片でリスト項目をクリックした場合しかし、私はこの例外を取得:これはなぜ起こるか

FATAL EXCEPTION: main 
java.lang.IllegalStateException: Activity has been destroyed 
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342) 
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578) 

誰でも知っていますか?私は同様の問題があった

おかげ

答えて

10

あなたがデバイスを回転すると、Androidは、セーブ破壊し、あなたのActivityFragmentsのそのViewPagerを再現。 ViewPagerActivityのを使用しているため、Fragmentsを保存して再利用します(新しいものは作成しません)。オリジナルのActivityの古い参照が保持され、IllegalStateExceptionになります。あなたの子供Fragments

、このような何かしてみてください:

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    Log.v(TAG, "onAttach"); 

    // Check if parent activity implements our callback interface 
    if (activity != null) { 
     try { 
      mParentCallback = (Callbacks) activity; 
     } 
     catch (ClassCastException e) { 
     } 
    } 
} 

を選択が発生したときに次に:

if(mParentCallback != null) { 
    mParentCallback.onItemSelected(selectedLink); 
} 

onAttachFragmentライフサイクルの一部として呼び出されますので、ごFragmentsが彼らを更新しますローテーション時のコールバック参照。

+0

残念ながら、これは動作しません。私の 'onAttach'メソッドは既にあなたが提供したもののように見えます。オリエンテーションの変更時に、私の 'onAttach'メソッドが再度呼び出されず、結果として私のコールバックが更新されていません。 親フラグメントに 'setRetainInstance(true)'があります。これは、この子フラグメントがデタッチされないようにしますか? – Milo

+0

'setRetainInstance(true)'が設定されていても 'onAttach'はまだ呼び出されているはずですので、ここで何か間違っているかもしれません。あなたのコールバックを設定して呼び出すことについてもっとコードを投稿できますか?また、 'setRetainInstance(true)'を使って、この質問に対する答えをチェックしてください。この状況では良い習慣ではありません。保存して状態を復元する必要があります。http://stackoverflow.com/questions/11182180/understanding-fragments- setretaininstanceboolean –

+3

解決策が見つかりました。 (FragmentActivity - >フラグメント1 - >フラグメント2(ViewPager付き) - > ViewPagerチャイルドフラグメント) コールバックをフラグメント1(onAttachとonDetachが呼び出されている)に移動しなければならなかったため、 。私はViewPagerの子フラグメントの 'onItemSelected'メソッドから親フラグメント(フラグメント1)のコールバックへ静的呼び出しを行いました。 これは少しハックしたようですが、うまく機能します。フラグメント1に 'setRetainInstance(true)'を使用するので、子フラグメントも状態を保持します。 – Milo

0

が、私は破片が保持されているので、それだと思うとdestoryed活動への参照を維持している、私の解決策は、活動中のフラグメントへの参照を維持するために例えばフラグメントmyfragmentました= null。そしてMyFragmentに次のコードを使用します。

public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     ((TestActivity)activity).contentFragment = this; 
} 
+0

これをもう少し説明してもらえますか、私は完全に理解しているか分かりません。親フラグメントのすべての子フラグメントへの参照を保持しますか?私の子フラグメントは多くの子フラグメントページを含むViewPagerなので、もし私がそれを助けることができれば、これらすべての静的なコピーを保持したくありません。ありがとう。 – Milo

0

同様の問題がありました。基本的には、ViewPagerに2つのフラグメントがある場合は、現在のアクティビティに参照を格納します。 pagerAdapterのgetItem()は、新しいフラグメントを作成し、アクティビティには関連付けられていないため、呼び出さないでください。そのため、「アクティビティが破棄されました」という例外が発生します。フラグメント参照を保持したくない場合は、findViewWithTag()メソッドを使用してFragmentオブジェクトを取得できます。

0

を以下のおかげで私は、ネストされたフラグメントおよびソリューションは、私のために働いたのstackoverflowのどれを使用してこの問題を抱えていました。単に破棄されたフラグメントが以前のアクティビティへのポインタを格納している場合、getFragmentManager()はすでに破壊されたアクティビティで呼び出されるためnullを返します)、それであなた自身でポインタを管理する必要があるのです。

:私はこのコードで終わったフラグメントを処理するアクティビティで
方法におけるI活動へのポインタを保存した第一のレベルの断片において

public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     parentActivity = activity; // parentActivity is static variable 
} 

2:私は、次の解決策になってしまいました

private void launchFragment(Fragment fragment, Activity parent) { 
      FragmentTransaction transaction; 
      if(parent == null) 
       transaction = mFragmentManager.beginTransaction(); 
      else // for nested child fragments, workaround for Android parent pointer bug 
       transaction = parent.getFragmentManager().beginTransaction(); 
      transaction.replace(R.id.container, fragment); 
      transaction.addToBackStack(null); 
      transaction.commit(); 
} 

第2レベルの(ネストされた)フラグメントを呼び出すときにのみ、FIRSTレベルのフラグメントのparentActivityを渡す必要があります。このバグは、フォアグラウンドからアプリケーションを取り込んだ後にネストされたものだけであるようです。

関連する問題