'IllegalStateException:活动已被销毁'当'getSupportFragmentManager()'在活动重新启动后调用
我有一个父级片段活动,它具有包含子ViewPager的ViewPager。子ViewPager包含每个页面的片段。我使用回调接口在这些子页面片段和顶层父页面片段活动之间进行通信。'IllegalStateException:活动已被销毁'当'getSupportFragmentManager()'在活动重新启动后调用
public interface Callbacks {
public void onItemSelected(Link link);
}
在父母片段活动中,我监听onItemSelected
事件,例如,
@Override
public void onItemSelected(Link link) {
Bundle argumentsFront = new Bundle();
argumentsFront.putParcelable(FragmentComments.ARG_ITEM_ID, link);
fragmentComments = new FragmentComments();
fragmentComments.setArguments(argumentsFront);
getSupportFragmentManager().beginTransaction().replace(R.id.post_container, fragmentComments).commitAllowingStateLoss();
}
现在这个工作正常,当应用程序第一次启动。
如果您打开设备更改方向,则重新启动“活动”。当我使用setRetainInstance(true);
(我没有在子ViewPager的页面Fragments中调用setRetainInstance(true),因为它不受支持),所有片段重新初始化自己。但是如果我在孩子的片段点击列表项ViewPager我得到这个异常:
FATAL EXCEPTION: main
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
有谁知道为什么会这样?
感谢
当你旋转设备,Android的节省,销毁,并重新创建你的Activity
和Fragments
其ViewPager
。由于ViewPager
使用您的Activity
的FragmentManager
,因此它会为您保存并重新使用这些Fragments
(并且不会创建新的),因此它们将保留对您的(现已销毁的)原始Activity
的旧引用,并获得IllegalStateException
。
在你的孩子Fragments
,尝试这样的事情:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.v(TAG, "onAttach");
// Check if parent activity implements our callback interface
if (activity != null) {
try {
mParentCallback = (Callbacks) activity;
}
catch (ClassCastException e) {
}
}
}
然后,当选择发生:
if(mParentCallback != null) {
mParentCallback.onItemSelected(selectedLink);
}
由于onAttach
被调用为Fragment
生命周期的一部分,你的Fragments
将更新自己的旋转时的回调引用。
我有一个类似的问题,我认为这是因为片段被保留,并保持到destoryed活动的参考,我的解决办法是保持在活动中如片段myfragment片段的引用= null。然后用下面的代码MyFragment:
public void onAttach(Activity activity) {
super.onAttach(activity);
((TestActivity)activity).contentFragment = this;
}
你能否再解释一下,我不确定我完全理解。您是否在父代片段Activity中保留对每个孩子片段的引用?我的孩子Fragment是一个ViewPager,其中包含许多子页面片段,所以我不想保留所有这些静态副本,只要我能帮助它。谢谢。 – Milo 2013-02-12 22:49:05
有类似的问题。基本上,如果ViewPager只有几个片段,那么在当前活动中存储对它们的引用。不要调用pagerAdapter的getItem(),因为它会创建一个新的片段,并且它不会附加到任何活动,这就是为什么我们看到“活动已被销毁”的例外。如果你不想保留片段引用,那么你可以使用findViewWithTag()方法来获取Fragment对象。
在OnPostResume回调中提交事务解决了我的问题。由于以下博文 http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
@Override
protected void onPostResume() {
super.onPostResume();
// Commit your transactions here.
}
我有这个问题与嵌套的片段,并没有计算器的解决方案为我工作。看起来,支持库存在一个bug,当被解散的片段仍然存储指向先前活动的指针时(所以getFragmentManager()仅返回null,因为它在已经销毁的活动上被调用),这就是为什么你需要自己管理指针。我结束了一个下列溶液:
1.在我在方法
public void onAttach(Activity activity) {
super.onAttach(activity);
parentActivity = activity; // parentActivity is static variable
}
2.在其处理片段我结束了该代码的活性保存指针活性的第一水平片段:
private void launchFragment(Fragment fragment, Activity parent) {
FragmentTransaction transaction;
if(parent == null)
transaction = mFragmentManager.beginTransaction();
else // for nested child fragments, workaround for Android parent pointer bug
transaction = parent.getFragmentManager().beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
只有当您调用SECOND级别(嵌套)片段时,您才应该传递FIRST级别片段的parentActivity,因为看起来该错误仅适用于将应用程序从前台移出后的嵌套片段。
不幸的是,这不起作用。我的'onAttach'方法看起来就像你提供的方法。在方向改变我的'onAttach'方法不会再次被调用,因此我的回调没有被更新。 父Fragment有'setRetainInstance(true)',我想这可以防止这个子Fragment被分离? – Milo 2013-02-12 22:45:51
即使设置了“setRetainInstance(true)”,根据文档'onAttach'仍然应该被调用,所以在这里可能会出现其他问题。你可以发布更多关于设置和调用回调的代码吗?此外,检查出这个问题的答案,使用'setRetainInstance(true)'在这种情况下不是一个好习惯,你应该保存并恢复状态 - http://stackoverflow.com/questions/11182180/understanding-fragments- setretaininstanceboolean – 2013-02-12 22:57:10
我找到了一个解决方案。由于已经嵌套片段是这样的: (FragmentActivity - >片段1 - >片段2(带ViewPager) - > ViewPager儿童片段) 我不得不回调移动到片段1(其中onAttach和onDetach正在调用) 。然后,我从ViewPager的子碎片中的'onItemSelected'方法向父Fragment(碎片1)中的回调进行静态调用。 这似乎有点黑客,但效果很好。我在片段1中使用'setRetainInstance(true)',这样子片段也保持状态。 – Milo 2013-02-13 09:21:48