如何在Backstack事务后保留片段数据?

时间:2013-06-22 15:18:49

标签: android android-fragments back-stack

我有一个活动,包含片段'list',点击其中一个项目后会将其自身替换为'content'片段。当用户使用后退按钮时,他再次被带到“列表”片段 问题是片段处于默认状态,无论我尝试保留数据。

事实:

  1. 这两个片段都是通过public static TheFragment newInstance(Bundle args)setArguments(args)Bundle args = getArguments()
  2. 创建的
  3. 两个片段都在同一级别,它直接位于父活动的FrameLayout内(即不是嵌套片段)
  4. 我不想调用setRetainInstance,因为我的活动是主/详细信息流,在大屏幕上有2个窗格布局。 7英寸平板电脑有1个纵向画面和2个横向画面。如果我保留'列表'片段实例,它(我认为)将屏幕旋转搞乱
  5. 当用户点击“列表”片段中的某个项目时,“内容”片段将通过FragmentTransaction#replace(int, Fragment, String)显示,其ID相同但标签不同
  6. 我确实覆盖了onSaveInstanceState(Bundle),但框架并没有始终,因为per the doc“在很多情况下,片段可能主要是拆除(例如放置在没有显示UI的后台堆栈上),但在其拥有的活动实际需要保存其状态之前,其状态将不会被保存。“
  7. 我正在使用支持库
  8. 从上面的子弹5中,我猜想片段事务后需要恢复内存的低端设备可能会调用Fragment#onSaveInstanceState(Bundle)。但是,在我的测试设备(Galaxy Nexus和Nexus 7)上,框架不会调用该方法。所以这不是一个有效的选择。

    那么,我如何保留一些片段数据呢?传递给Fragment#onCreateFragment#onActivityCreated等的捆绑包始终是null

    因此,我无法从全新的片段启动到后台堆栈恢复发挥作用。

    注意:可能related/duplicate question

1 个答案:

答案 0 :(得分:10)

这似乎不对,但这就是我最终做的事情:

public class MyActivity extends FragmentActivity {
    private Bundle mMainFragmentArgs;

    public void saveMainFragmentState(Bundle args) {
        mMainFragmentArgs = args;
    }

    public Bundle getSavedMainFragmentState() {
        return mMainFragmentArgs;
    }

    // ...
}

在主要片段中:

public class MainFragment extends Fragment {
    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle args = ((MyActivity) getActivity()).getSavedMainFragmentState();

        if (args != null) {
            // Restore from backstack
        } else if (savedInstanceState != null) {
            // Restore from saved instance state
        } else {
            // Create from fragment arguments
            args = getArguments();
        }

        // ...
    }

    // ...

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Bundle args = new Bundle();
        saveInstance(args);
        ((MyActivity) getActivity()).saveMainFragmentState(args);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveInstance(outState);
    }

    private void saveInstance(Bundle data) {
        // put data into bundle
    }
}

有效!

  • 如果从backstack返回,则片段使用onDestroyView
  • 中保存的参数
  • 如果从其他应用/进程/内存不足返回,则片段将从onSaveInstanceState
  • 恢复
  • 如果是第一次创建,则片段使用setArguments
  • 中设置的参数

涵盖所有活动,并始终保留最新鲜的信息。

它实际上更复杂,它基于interface,来自onAttach / onDetach的侦听器未注册/注册。但原则是一样的。