【问题标题】:Saving and restoring state in nested fragments在嵌套片段中保存和恢复状态
【发布时间】:2014-08-06 15:58:04
【问题描述】:

我阅读了许多已经处理过类似问题但无法找到完全回答我问题的帖子。

我有一个使用嵌套片段(来自 v4 支持库)的 Android 应用。我有一个包含片段的主要 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 始终为空。 我还应该指出,调用this.setRetainInstance() 会引发异常:“无法保留嵌套在其他片段中的片段”。

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

【问题讨论】:

  • 您找到解决方案了吗?拉尔夫

标签: java android android-fragments


【解决方案1】:

我遇到了类似的问题,正在寻找解决问题的提示。最终,我意识到我的父片段的 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,并恢复到我想要的样子。

【讨论】:

  • 好的,这部分工作,但下一个错误是,如果有一个 savedInstanceState 并且我跳过创建一个新片段,那么 mChildFragment 为空,这会导致 NPE 稍后。这个答案建议在片段上使用标签并对其进行测试,而不是测试捆绑包,作为这样做的更好方法......stackoverflow.com/questions/5164126/…
【解决方案2】:

如果您使用 setRetainInstance(true),那么捆绑包当然是空的。

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

只需尝试删除 setRetainInstance(true)。

【讨论】:

  • 我不使用 setRetainInstance(),只是指出当我尝试使用它时会引发异常
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

    嵌套片段似乎没有一种简单的方法来保留信息。我的解决方案是让父片段保留在 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()
          }
    
        }
    

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 1970-01-01
      • 2013-04-04
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 2014-01-11
      • 1970-01-01
      相关资源
      最近更新 更多