在嵌套片段中保存和恢复状态

时间:2014-08-06 15:58:05

标签: java android android-fragments

我阅读了许多已经处理过类似问题的帖子,但我们找不到能完全回答我问题的内容。

我有一个使用嵌套片段的Android应用程序(来自v4支持库)。我有一个包含片段的主FragmentActivity,该片段包含一个ViewPager,可以在3个内部片段之间滑动。 我希望能够保存3个内部嵌套片段中每个片段的状态,为此,我为3个内部片段中的每个片段覆盖了onSaveInstanceState()方法,并尝试在onActivityCreated()中恢复状态,像这样:

InternalFragment1.java:

public class InternalFragment1 extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);

        // Commands to attach to main UI components...

        if(savedInstanceState != null) {
            // Commands to restore the saved state...
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Commands to save the state into outState...
        super.onSaveInstanceState(outState);
    }
}

但是,当调用onActivityCreated()时,无论是否存在已保存的状态,savedInstanceState始终为null。 我还应该指出,调用this.setRetainInstance()会引发异常,说明:"不能保留嵌套在其他片段中的片段"。

如何正确保存和恢复嵌套片段'状态?

4 个答案:

答案 0 :(得分:1)

如果你使用setRetainInstance(true),那么bundle当然是null。

片段不会被破坏,只会从当前活动中分离并附加到新活动。只有当片段被销毁时,才会获得一个包含你在onSaveInstanceState中保存的值的包。

尝试删除setRetainInstance(true)。

答案 1 :(得分:0)

这是父片段保留时可能遇到的问题。

你可以试试这个: http://ideaventure.blogspot.lu/2014/10/nested-retained-fragment-lost-state.html

但我最好建议删除parentFragment上的setRetaining()。

答案 2 :(得分:0)

嵌套片段似乎没有一种简单的方法来保留信息。我的解决方案是让父片段保持在Bundles的映射上,并且嵌套的片段在onCreate期间获得它们自己的片段。最大的问题是每个嵌套片段不能有多个实例。

Ex(对不起,这是在Kotlin,但在Java中也是如此)

    class ParentFragment : Fragment(), ParentFragmentListener {
      val bundles = SparseArray<Bundle>()

      fun getChildBundle(fragmentId : Int) : Bundle {
              if (bundles.get(fragmentId) == null) {
                val bundle = Bundle()
                bundles.put(fragmentId,bundle)
                return bundle
            }

            return bundles.get(fragmentId)
      }
    }

    interface ParentFragmentListener {
      fun getChildBundle(fragmentId : Int) : Bundle
    }

    class ChildFragment : Fragment() {
      lateinit var childBundle : Bundle

      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val listener = parentFragment as? ParentFragmentListener
        val childBundle = listener?.getFragmentsSavedBundle(UNIQUE_FRAGMENT_ID)
        if (childBundle != null) this.childBundle = childBundle else childBundle = Bundle()
      }

    }

答案 3 :(得分:0)

我有一个类似的问题,正在寻找解决它的提示。最后,我意识到我的父片段的onCreateView包括:

        mChildFragment = ChildFragment.newInstance(mId);
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, mChildFragment).commit();

当然,这会创建子片段的新实例,该实例具有savedInstanceState的空包。用条件围绕上面的块:

    if(savedInstanceState == null) {
        mChildFragment = ChildFragment.newInstance(mId);
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, mChildFragment).commit();
    }

似乎使它工作,因为现在子片段中的onCreate看到我在onSaveInstanceState中为它创建的非null savedInstanceState,并恢复到我想要的状态。