不能保留嵌套片段(Can't retain nested fragments)

2019-07-19 19:25发布

是否有保存嵌套片段的状态的另一种方式? 或者,如果我们不应该这样做,为什么呢? 谢谢 !

02-13 11:42:43.258: E/AndroidRuntime(7167): java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
02-13 11:42:43.258: E/AndroidRuntime(7167):     at android.support.v4.app.Fragment.setRetainInstance(Fragment.java:742)

Answer 1:

您可以使用FragmentManager.saveFragmentInstanceState(Fragment)来检索片段状态。 返回值实现Parcelable,所以你可以把它放在一个包。

对于修复,您可以创建一个使用该片段后提供状态Fragment.setInitialSavedState(Fragment.SavedState)



Answer 2:

由于支持库20+( https://code.google.com/p/android/issues/detail?id=74222 ),有与实例休闲儿童片段中的错误,有它修复- HTTP:/ /ideaventure.blogspot.com.au/2014/10/nested-retained-fragment-lost-state.html

从网页(添加到您的父母片段)代码 -

private FragmentManager childFragmentManager() {//!!!Use this instead of getFragmentManager, support library from 20+, has a bug that doesn't retain instance of nested fragments!!!!
        if(mRetainedChildFragmentManager == null) {
            mRetainedChildFragmentManager = getChildFragmentManager();
        }
        return mRetainedChildFragmentManager;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (mRetainedChildFragmentManager != null) {
            //restore the last retained child fragment manager to the new
            //created fragment
            try {
                Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager");
                childFMField.setAccessible(true);
                childFMField.set(this, mRetainedChildFragmentManager);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

    }


Answer 3:

问题: mChildFrgamentManager被重新创建( https://code.google.com/p/android/issues/detail?id=74222 )
解决方法:保留mChildFrgamentManager如果片段具有setRetainInstance(true)

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if (getRetainInstance()) {
        if (mRetainedChildFragmentManager != null) {
            try {
                Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager");
                childFMField.setAccessible(true);
                childFMField.set(this, mRetainedChildFragmentManager);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            mRetainedChildFragmentManager = getChildFragmentManager();
        }
    }
}

警告:有了这个代码, setRetainInstace前应称为onAttach

PS:这是@attels答案有点改进版。



Answer 4:

这不再是最新的支持库的限制,这之后AOSP提交 。

下面是提交信息:

许可证setRetainInstance(真)上嵌套片段

保存跨越配置的变化任意嵌套片段作为nonconfiguration对象。 这允许使用保留实例子片段等片段内,任意不透明的依赖。



文章来源: Can't retain nested fragments