我的活动中有几个片段。完成一些过程后,我使用下面的代码关闭片段。
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();
}
}
对于 ViewPager2 只需使用
viewPager.setSaveEnabled(false);
在 ViewPager 适配器中,覆盖
restoreState(state, loader)
@Override
public void restoreState(final Parcelable state, final ClassLoader loader) {
try {
super.restoreState(state, loader);
} catch (Exception e) {
e.printStackTrace();
}
}
请按照以下步骤添加活动中的片段
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;
在 Fragment 类中添加以下代码,根据 doc,它返回 Transition,用于在 Fragment 准备关闭时将视图移出场景。
@Override
public Object getReturnTransition() {
return super.getReturnTransition();
}
您的堆栈跟踪显示您正在使用
ViewPager
并自己操作后堆栈。
这可能不是一个好主意 - 要么让你的
ViewPager
管理后退堆栈(它做得很好),要么完全你自己管理。
请注意,在自己管理后台堆栈时,您必须考虑恢复实例状态(堆栈跟踪中的功能)和Fragment 生命周期。
这意味着在内存不足的情况下,您的 Activity 和 Fragments 将停止。如果您没有正确保存实例状态,当它们重新启动时,您将收到类似上述错误。如果您的片段的工作流程很简单,您可以使用
ViewPager
来避免所有这些。
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();
}
首先,你不需要打电话
getActivity().getSupportFragmentManager()
。 getFragmentManager()
就可以拨打 FragmentManager
。
如果你在 Support Fragment getFragmentManager() 会给你
supportFragmentManager()
或者它会给你 app.Fragment Manager。
如果你在ViewPager内部调用PopBackstack,它将不起作用。如果您在另一个片段中使用
viewPager
。您应该仅在父片段中调用 popBackstack
。不在viewPager
中。
尝试下面的代码,它将根据返回堆栈名称清除堆栈。
getFragmentManager.popBackStackImmediate(YourBackStackName, FragmentManager.POP_BACK_STACK_INCLUSIVE)
希望有帮助:)
重写 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()
}
}
}
在报错的Fragment的Adapter中重写以下方法,返回null。
@Override
public Parcelable saveState() {
return null;
}
更多详情这里。
当
viewPagerAdapter
(在 ViewPager2->restorePendingState->restoreState 中)变为 null 时,会发生这种情况,但 ViewPager2->restorePendingState 仍然收到它。
尝试在此行标记停止断点或重新安装应用程序
void 位于 androidx.viewpager2.widget.ViewPager2
private void restorePendingState() {
...
Adapter<?> adapter = getAdapter();
if (adapter == null) {
return;
}
...
}
使用
viewPager.setSaveEnabled(false)
有效,但保存视图的状态将被禁用,我不希望发生这种情况。我想在可能的情况下恢复状态,并且在引发异常的情况下只需捕获它而不恢复状态。
您无法覆盖 ViewPager 适配器中的 restoreState(state, loader)
,因为该方法是最终方法,但是您可以在 Activity 的 onStart
方法中捕获异常:
@Override
protected void onStart() {
try {
super.onStart();
}catch (IllegalStateException e) {
e.printStackTrace();
}
}