我有一个父片段活动,其中包含一个包含子ViewPager的ViewPager。子ViewPager包含每个页面的片段。我使用回调接口(例如
)在这些子页面片段和顶级父片段活动之间进行通信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的页面片段中调用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)
有谁知道为什么会这样?
由于
答案 0 :(得分:11)
当您旋转设备时,Android会保存,销毁并重新创建Activity
及其ViewPager
Fragments
。由于ViewPager
使用FragmentManager
的{{1}},因此会为您保存并重复使用Activity
(并且不会创建新的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
将在轮换时更新其回调引用。
答案 1 :(得分:0)
我有一个类似的问题,我认为这是因为片段被保留并且保持对被破坏活动的引用,我的解决方案是保持对活动中片段的引用,例如Fragment myfragment = null。然后在MyFragment中使用以下代码:
public void onAttach(Activity activity) {
super.onAttach(activity);
((TestActivity)activity).contentFragment = this;
}
答案 2 :(得分:0)
有类似的问题。基本上,如果ViewPager只有几个片段,那么在当前活动中存储对它们的引用。不要调用pagerAdapter的getItem(),因为它创建了一个新的片段,它没有附加到任何活动,这就是为什么我们看到“Activity已被销毁”的例外。如果您不想保留片段引用,则可以使用findViewWithTag()方法获取Fragment对象。
答案 3 :(得分:0)
在OnPostResume回调中提交事务为我解决了这个问题。感谢以下博客 http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
@Override
protected void onPostResume() {
super.onPostResume();
// Commit your transactions here.
}
答案 4 :(得分:0)
我有嵌套片段的这个问题,没有一个stackoverflow解决方案适合我。看来,支持库存在一个错误,当被解散的片段仍然存储指向前一个活动的指针时(因此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,因为在您从前台启动应用程序后,似乎此错误仅适用于嵌套的。