首页 文章

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

提问于
浏览
2

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

我有一个使用嵌套片段的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() 会抛出一个异常,说明:"Can't retain fragments that are nested in other fragments" .

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

4 回答

  • 1

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

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

    只是尝试删除setRetainInstance(true) .

  • 0

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

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

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

  • 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()
          }
    
        }
    
  • 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,并恢复到我想要的状态 .

相关问题