web-dev-qa-db-ja.com

FragmentStatePagerAdapter IllegalStateException:<MyFragment>は現在FragmentManagerにありません

FragmentStatePagerAdapterを使用するアクティビティの一部のケース(onResume())でこれを取得しています。デバイスの戻るボタンを使用する場合。常にではない。再現できません。

私はサポートパッケージv4、最後のリビジョン(8)を使用しています。

すでにグーグルで検索しましたが、有用な答えを見つけることができませんでした。

ソースを見ると、ここにスローされます:FragmentManager.Java

@Override
public void putFragment(Bundle bundle, String key, Fragment fragment) {
    if (fragment.mIndex < 0) {
        throw new IllegalStateException("Fragment " + fragment
                + " is not currently in the FragmentManager");
    }
    bundle.putInt(key, fragment.mIndex);
}

しかし、なぜフラグメントのインデックスが0未満なのですか?

フラグメントをインスタンス化するコード:

@Override
public Fragment getItem(int position) {
    Fragment fragment = null;

    switch(position) {
        case 0:
            fragment = MyFragment.newInstance(param1);
            break;
        case 1:
            fragment = MyFragment2.newInstance(param2, param3);
            break;
    }
    return fragment;
}

@Override
public int getCount() {
    return 2;
}
28
Ixx

理由は、onResume()で毎回アダプタをインスタンス化しているためです。

アダプタのインスタンスを1回だけ作成すると、アクティビティのライフサイクルで、これが発生しなくなります。

5
Ixx

ViewPagerが(アクティビティではなく)フラグメント内にレイアウトされている場合:

mViewPager.setAdapter(new MyFragmentStatePagerAdapter(getFragmentManager()));

15
Thomas G.

ここでも同じエラーが発生しましたが、別の理由があります。

私の場合、私のFragmentStatePagerAdapterでgetItemPositionをオーバーライドしました。私のアイデアは、アイテムが存在する場合は位置を返すことであり、アイテムが存在しない場合はPOSITION_NONEを返すことでした。

さて、私の問題は、コレクションが空になるとPOSITION_NONEを返すということでした。そして、それはすべてを壊しました。

私の修正は、空のコレクションがあるときにPOSITION_UNCHANGEDを​​返すことでした。

それが他の誰かを助けることを願っています。

10
laggedHero

バグを理解するための2つの重要な点は次のとおりです。

  1. それは起こります時々
  2. onResume()で発生します。

この情報を踏まえると、ViewPagerFragmentsの状態を保持していない可能性があります。 FragmentからActivitysを直接操作している場合、ページ外のFragmentが破壊され、Activityが試行している可能性がありますnullフラグメントを操作します。現在の画面にない場合でもFragmentの状態を保持するには、修正は非常に簡単です。

private static final int NUM_ITEMS = 2;

ViewPager mPager = /** instantiate viewpager **/;
mPager.setOffscreenPageLimit(NUM_ITEMS-1);

あなたはそれについてここで読むことができます:

ViewPagerフラグメントは時間の経過とともに破壊されますか?

8
Alex Lockwood

この例外は、フラグメントを添付するための正しい状態ではなくなったアクティビティにフラグメントを添付しようとしていることを意味します。つまり、フラグメントをアタッチしようとするたびに(特に非同期呼び出しを介して)、誰かが戻るボタンを押して、アタッチ中にアクティビティが破壊される可能性が少しありますフラグメント。これは、単なる競合状態であるため常に再現可能であるとは限らず、常に発生するとは限りません。

これを修正するには2つの方法があります。

1)これは、アクティビティのonSaveInstanceStateが呼び出され、フラグメントを添付しようとしていることを投稿したときに発生します。Androidは現在フラグメントの状態を保存できないため、例外がスローされます。これを克服し、フラグメントの状態を保存していない場合は、

commitAllowingStateLoss()、トランザクションのコミット中。

2)非常に安全であるために、フラグメントを添付する前に、アクティビティが正しい状態かどうかを確認し、onPauseで次のコードを使用します。

    boolean isInCorrectState;

    public void onCreate{
    super.onCreate();
    isInCorrectState = true;
    }

    public void onPause() {
    super.onPause();
      if(isFinishing()){
        isInCorrectState = false;
       }
    }

フラグメントをアタッチする前に、このフラグを使用してアクティビティが正しい状態にあるかどうかを確認してください。つまり、フラグメントiff isInCorrectState == trueをアタッチします。

4
Vivek Soneja

私にとって理由は何か他のものでした。

私のLoader.onLoaderReset()では、アダプターからデータをクリアしました。アプリを離れるときに、onDestroy()によってローダーがリセットされ、FragmentStatePagerAdapterがクリアされました。アダプターがフラグメントへのすべての参照をクリアする原因になったと思いますが、どういうわけか、FragmentManagerは気付かず、例外をスローしました。私にはあまり論理的ではないようです。

私にとってそれはActivity.onDestroy()が起こったことに注意してください。

それが誰かを助けることを願っています。

2
Michał K

ViewPagerのフラグメントが修正されました。アダプターのフラグメントを置き換えたり、別のフラグメントのセットを提供してnotifyDataSetを変更したりするか、FrameLayoutを利用して、ビューページャータブの現在のフラグメントに別のフラグメントを表示します。

うまくいく私の解決策があります:

フラグメントレベルで適用されたスワイプジェスチャーと、ViewPagerがデフォルトのスワイプが無効になっている状態

0
Abhinav Saxena