PagerAdapter.getItem() 崩溃并出现 IllegalStateException:片段已添加
PagerAdapter.getItem() crash with IllegalStateException: Fragment already added
我有 FragmentStatePagerAdapter.getItem() 的代码:
(logd()只是调用Log.d()的静态方法)。
@Override
public Fragment getItem(int position) {
logd("Fragment for position: " + position);
Fragment currFragment = null;
List<Fragment> allFragments = mFragmentManager.getFragments();
if (allFragments.size() == 0) {
logd("No Fragments cached.");
} else {
currFragment = allFragments.get(position);
logd("Found a cached Fragment: " + currFragment);
}
if (currFragment == null) {
currFragment = MyCustomFragment.create(position);
}
logd("Returning Fragment: Position: " + position + " Fragment: " + currFragment.toString());
return currFragment;
}
但它总是崩溃:
--------- beginning of crash
2020-07-27 10:45:44.492 6271-6271/com.example.package E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.package, PID: 6271
java.lang.IllegalStateException: Fragment already added: MyCustomFragment{7c7e778} (5f284a0f-a00f-4be2-8098-a3e8dc65c9cb) id=0x7f09024e}
at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
这让我完全难住了。有人可以帮助解释为什么会发生这种崩溃吗?
据我所知,相同的代码结构在我的应用程序的其他地方也有效。
我确实看到了其他几个具有相同异常的 SO 问题,但是 none 专门处理 ViewPager+TabLayout 组合中的片段。
编辑:即使这段代码也会因同样的异常而崩溃:
@Override
public Fragment getItem(int position) {
Fragment currFragment = MyCustomFragment.create(position);
logd("Returning Fragment: Position: " + position + " Fragment: " + currFragment.toString());
return currFragment;
}
编辑:添加 MyCustomFragment.create() 的代码:
public static MyCustomFragment create(int position) {
Bundle args = new Bundle();
args.putInt("position", position);
MyCustomFragment f = new MyCustomFragment();
f.setArguments(args);
logd("Creating Fragment at position: " + position);
return f;
}
编辑:
似乎如果我 return 从 getItem() 新建 Fragment(),一切正常。如果我 return 从 getItem() 新建 MyCustomFragment(),我就会崩溃。 MyCustomFragment 甚至没有任何构造函数;它依赖于默认的(尽管我确实尝试使用仅调用 super() 的无参数构造函数;但崩溃仍然存在)。
您不能在其他地方使用已添加的 Fragment
。当这行代码执行时:
currFragment = allFragments.get(position);
根据log
,这意味着您列表中的fragment
已经添加到某个地方(在不同的地方或非常相同的地方)。也就是说,在getItem(int position)
中,只能添加一个Fragment
的新实例。所以删除这个代码块:
else {
currFragment = allFragments.get(position);
logd("Found a cached Fragment: " + currFragment);
}
这个 exception
应该消失了。
问题在于,在 MyCustomFragment 中,在 onCreateView() 方法中,return super.onCreateView()
的 IDE-stub 代码被无意中留在原地。超类 Fragment 在某些条件下从其 onCreateView() 中 returns null。看来是来自 onCreateView() 的 null return 造成了问题。我在 MyCustomFragment 的 onCreateView() 中膨胀了一个测试布局,现在崩溃消失了。
如果情况确实如此,则例外情况看起来措辞不正确。
我有 FragmentStatePagerAdapter.getItem() 的代码:
(logd()只是调用Log.d()的静态方法)。
@Override
public Fragment getItem(int position) {
logd("Fragment for position: " + position);
Fragment currFragment = null;
List<Fragment> allFragments = mFragmentManager.getFragments();
if (allFragments.size() == 0) {
logd("No Fragments cached.");
} else {
currFragment = allFragments.get(position);
logd("Found a cached Fragment: " + currFragment);
}
if (currFragment == null) {
currFragment = MyCustomFragment.create(position);
}
logd("Returning Fragment: Position: " + position + " Fragment: " + currFragment.toString());
return currFragment;
}
但它总是崩溃:
--------- beginning of crash
2020-07-27 10:45:44.492 6271-6271/com.example.package E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.package, PID: 6271
java.lang.IllegalStateException: Fragment already added: MyCustomFragment{7c7e778} (5f284a0f-a00f-4be2-8098-a3e8dc65c9cb) id=0x7f09024e}
at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
这让我完全难住了。有人可以帮助解释为什么会发生这种崩溃吗?
据我所知,相同的代码结构在我的应用程序的其他地方也有效。
我确实看到了其他几个具有相同异常的 SO 问题,但是 none 专门处理 ViewPager+TabLayout 组合中的片段。
编辑:即使这段代码也会因同样的异常而崩溃:
@Override
public Fragment getItem(int position) {
Fragment currFragment = MyCustomFragment.create(position);
logd("Returning Fragment: Position: " + position + " Fragment: " + currFragment.toString());
return currFragment;
}
编辑:添加 MyCustomFragment.create() 的代码:
public static MyCustomFragment create(int position) {
Bundle args = new Bundle();
args.putInt("position", position);
MyCustomFragment f = new MyCustomFragment();
f.setArguments(args);
logd("Creating Fragment at position: " + position);
return f;
}
编辑:
似乎如果我 return 从 getItem() 新建 Fragment(),一切正常。如果我 return 从 getItem() 新建 MyCustomFragment(),我就会崩溃。 MyCustomFragment 甚至没有任何构造函数;它依赖于默认的(尽管我确实尝试使用仅调用 super() 的无参数构造函数;但崩溃仍然存在)。
您不能在其他地方使用已添加的 Fragment
。当这行代码执行时:
currFragment = allFragments.get(position);
根据log
,这意味着您列表中的fragment
已经添加到某个地方(在不同的地方或非常相同的地方)。也就是说,在getItem(int position)
中,只能添加一个Fragment
的新实例。所以删除这个代码块:
else {
currFragment = allFragments.get(position);
logd("Found a cached Fragment: " + currFragment);
}
这个 exception
应该消失了。
问题在于,在 MyCustomFragment 中,在 onCreateView() 方法中,return super.onCreateView()
的 IDE-stub 代码被无意中留在原地。超类 Fragment 在某些条件下从其 onCreateView() 中 returns null。看来是来自 onCreateView() 的 null return 造成了问题。我在 MyCustomFragment 的 onCreateView() 中膨胀了一个测试布局,现在崩溃消失了。
如果情况确实如此,则例外情况看起来措辞不正确。