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;
}
理由は、onResume()で毎回アダプタをインスタンス化しているためです。
アダプタのインスタンスを1回だけ作成すると、アクティビティのライフサイクルで、これが発生しなくなります。
ViewPagerが(アクティビティではなく)フラグメント内にレイアウトされている場合:
mViewPager.setAdapter(new MyFragmentStatePagerAdapter(get子FragmentManager()));
ここでも同じエラーが発生しましたが、別の理由があります。
私の場合、私のFragmentStatePagerAdapterでgetItemPositionをオーバーライドしました。私のアイデアは、アイテムが存在する場合は位置を返すことであり、アイテムが存在しない場合はPOSITION_NONEを返すことでした。
さて、私の問題は、コレクションが空になるとPOSITION_NONEを返すということでした。そして、それはすべてを壊しました。
私の修正は、空のコレクションがあるときにPOSITION_UNCHANGEDを返すことでした。
それが他の誰かを助けることを願っています。
バグを理解するための2つの重要な点は次のとおりです。
onResume()
で発生します。この情報を踏まえると、ViewPager
がFragment
sの状態を保持していない可能性があります。 Fragment
からActivity
sを直接操作している場合、ページ外のFragment
が破壊され、Activity
が試行している可能性がありますnull
フラグメントを操作します。現在の画面にない場合でもFragment
の状態を保持するには、修正は非常に簡単です。
private static final int NUM_ITEMS = 2;
ViewPager mPager = /** instantiate viewpager **/;
mPager.setOffscreenPageLimit(NUM_ITEMS-1);
あなたはそれについてここで読むことができます:
この例外は、フラグメントを添付するための正しい状態ではなくなったアクティビティにフラグメントを添付しようとしていることを意味します。つまり、フラグメントをアタッチしようとするたびに(特に非同期呼び出しを介して)、誰かが戻るボタンを押して、アタッチ中にアクティビティが破壊される可能性が少しありますフラグメント。これは、単なる競合状態であるため常に再現可能であるとは限らず、常に発生するとは限りません。
これを修正するには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をアタッチします。
私にとって理由は何か他のものでした。
私のLoader.onLoaderReset()
では、アダプターからデータをクリアしました。アプリを離れるときに、onDestroy()によってローダーがリセットされ、FragmentStatePagerAdapter
がクリアされました。アダプターがフラグメントへのすべての参照をクリアする原因になったと思いますが、どういうわけか、FragmentManager
は気付かず、例外をスローしました。私にはあまり論理的ではないようです。
私にとってそれはActivity.onDestroy()
が起こったことに注意してください。
それが誰かを助けることを願っています。
ViewPagerのフラグメントが修正されました。アダプターのフラグメントを置き換えたり、別のフラグメントのセットを提供してnotifyDataSetを変更したりするか、FrameLayoutを利用して、ビューページャータブの現在のフラグメントに別のフラグメントを表示します。
うまくいく私の解決策があります: