java.lang.IllegalStateException:键 f0 的片段不再存在:索引 1
Posted
技术标签:
【中文标题】java.lang.IllegalStateException:键 f0 的片段不再存在:索引 1【英文标题】:java.lang.IllegalStateException: Fragment no longer exists for key f0: index 1 【发布时间】:2018-01-25 20:17:14 【问题描述】:我在一个 Activity 中有几个片段。完成一些过程后,我将使用以下代码关闭片段。
if (getActivity().getSupportFragmentManager().getBackStackEntryCount() > 0)
getActivity().getSupportFragmentManager().popBackStackImmediate();
但是在 popBackStackImmediate() 线上它会抛出错误
Process: com.TestProject.testpro, PID: 17966
java.lang.IllegalStateException: Fragment no longer exists for key f0: index 1
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:879)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:215)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1481)
at android.view.View.dispatchRestoreInstanceState(View.java:14746)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3121)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3127)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3127)
at android.view.View.restoreHierarchyState(View.java:14724)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:475)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:807)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2360)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2149)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2103)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:823)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:776)
at com.TestProject.testpro.application.fragments.WFMUpgradeToAffinityFragmentAN$WFMStoreProfileIdReceiver.onReceive(WFMUpgradeToAffinityFragmentAN.java:1064)
at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:297)
at android.support.v4.content.LocalBroadcastManager.access$000(LocalBroadcastManager.java:46)
at android.support.v4.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:116)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
没有其他关闭片段的崩溃。我找不到这个问题的确切解决方案。请帮我解决这个问题。
编辑:
我正在使用下面的函数来调用片段。
void showContentFragment(Fragment newFragment, String backStackName)
//Log.e(TAG, "showContentFragment- " + "BackstackName: "+ backStackName);
FragmentManager mFragmentManager = getActivity().getSupportFragmentManager();
if (newFragment != null)
//updateNavigation(backStackName);
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.replace(R.id.fragment_container, newFragment);
if (backStackName != null && !backStackName.isEmpty())
ft.addToBackStack(backStackName);
ft.commit();
【问题讨论】:
你试过只使用popBackStack()
吗?
@Kiya 是的,我试过了。还是没有运气。
您是否将片段添加到后台堆栈?请在您在活动中添加片段的位置发布您的代码。
为什么需要手动执行此操作? getActivity().onBackPressed() 应该足以返回到上一个片段,以防你做得正确。
@Sniper 你解决了这个问题吗?
【参考方案1】:
对于 ViewPager2,只需使用 viewPager.setSaveEnabled(false);
【讨论】:
是的,它有效,我认为它来自***.com/questions/59486504/…。【参考方案2】:在 ViewPager 适配器中,覆盖 restoreState(state, loader)
@Override
public void restoreState(final Parcelable state, final ClassLoader loader)
try
super.restoreState(state, loader);
catch (Exception e)
e.printStackTrace();
【讨论】:
很遗憾,这不适用于 ViewPager2。 restoreState 被声明为 final。【参考方案3】:请按照以下步骤从您的活动中添加片段
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, yourFragment, yourFragment.class.getSimpleName()).addToBackStack(yourFragment.class.getSimpleName())
.commit();
使用此代码从您的片段中调用popBackStack()
if (getFragmentManager().getBackStackEntryCount() > 0)
getFragmentManager().popBackStack();
确保您正在导入正确的片段类
import android.support.v4.app.Fragment;
【讨论】:
我遵循上述相同的步骤。仍然面临这个问题。【参考方案4】:在您的 Fragment 类中添加下面的代码,根据doc,它返回用于在 Fragment 准备关闭时将视图移出场景的转换。
@Override
public Object getReturnTransition()
return super.getReturnTransition();
【讨论】:
也添加了这个。它仍然崩溃。 是的。同样的崩溃。【参考方案5】:您的堆栈跟踪显示您正在使用ViewPager
并自己操作后台堆栈。
这可能不是一个好主意——要么让你的ViewPager
管理后台堆栈(它做得很好),要么完全自己管理。
请注意,在自己管理后台堆栈时,您必须考虑恢复实例状态(堆栈跟踪中的功能)和Fragment lifecycle。
这意味着在内存不足的情况下,您的 Activity 和 Fragments 将停止。如果您没有正确保存实例状态,当它们重新启动时,您将收到类似上述错误。如果您的 Fragments 的工作流程很简单,您可以使用 ViewPager
来避免所有这些。
【讨论】:
【参考方案6】:public void showContentFragment(Fragment fragment, Bundle bundle, boolean addToBackStack)
if (bundle != null)
fragment.setArguments(bundle);
tag = fragment.getClass().getSimpleName();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.container_internal, fragment, tag);
fragment.setRetainInstance(true); // IMPORTANT
if (addToBackStack)
ft.addToBackStack(tag);
try
ft.commit();
catch (Exception ex)
ex.printStackTrace();
ft.commitAllowingStateLoss();
【讨论】:
【参考方案7】:首先,您无需致电getActivity().getSupportFragmentManager()
。 getFragmentManager()
足以拨打FragmentManager
。
如果您在 Support Fragment 中,getFragmentManager() 会给您supportFragmentManager()
或者它会给您app.Fragment Manager。
如果您在 ViewPager 中调用 PopBackstack,它将不起作用。如果您在另一个片段中使用viewPager
。你应该只在父片段中调用popBackstack
。不在viewPager
。
试试下面的代码,它会根据返回的堆栈名称清除堆栈。
getFragmentManager.popBackStackImmediate(YourBackStackName, FragmentManager.POP_BACK_STACK_INCLUSIVE)
文档:https://developer.android.com/reference/android/app/FragmentManager.html#popBackStackImmediate(java.lang.String, int)
希望对你有帮助:)
【讨论】:
【参考方案8】:在我的 viewPager 中覆盖 restoreState 方法对我有用。
override fun restoreState(state: Parcelable?, loader: ClassLoader?)
try
super.restoreState(state, loader)
catch (e: Exception)
e.printStackTrace()
这是我的视图寻呼机的最终代码
class MenuTabAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm)
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
private var mCurrentPosition = -1
override fun getItem(position: Int): Fragment
return mFragmentList[position]
override fun getCount(): Int
return mFragmentList.size
fun addFragment(fragment: Fragment, title: String)
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
override fun getPageTitle(position: Int): CharSequence?
return mFragmentTitleList[position]
override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any)
super.setPrimaryItem(container, position, `object`)
if (position !== mCurrentPosition && container is HeightWrappingViewPager)
val fragment = `object` as Fragment
if (fragment?.view != null)
mCurrentPosition = position
container.requestLayout()
override fun restoreState(state: Parcelable?, loader: ClassLoader?)
try
super.restoreState(state, loader)
catch (e: Exception)
e.printStackTrace()
【讨论】:
【参考方案9】:这个崩溃什么时候发生?
当ViewPager包裹Fragment时,Fragment内部有ViewPager包裹Fragment。 当外层Fragment或内层Adapter继承FragmentStatePagerAdapter,或两者都继承FragmentStatePagerAdapter时。如何修复?
在报错的Fragment的Adapter中重写如下方法,返回null。
@Override
public Parcelable saveState()
return null;
更多详情here.
【讨论】:
以上是关于java.lang.IllegalStateException:键 f0 的片段不再存在:索引 1的主要内容,如果未能解决你的问题,请参考以下文章