10

我有一个包含片段“列表”的活动,单击其中一个项目时,它会将自身替换为“内容”片段。当用户使用后退按钮时,他再次被带到“列表”片段。
问题是片段处于其默认状态,无论我尝试什么持久化数据。

事实:

  1. 两个片段都是通过public static TheFragment newInstance(Bundle args),setArguments(args)Bundle args = getArguments()
  2. 两个片段都在同一级别,直接位于FrameLayout父活动的 a 内部(即不是嵌套片段)
  3. 我不想打电话setRetainInstance,因为我的活动是一个主/细节流,它在较大的屏幕上有一个 2 窗格布局。7" 平板电脑有 1 个纵向窗格和 2 个横向窗格。如果我保留“列表”片段实例,它会(我认为)屏幕旋转搞砸
  4. 当用户点击'list'片段中的一个项目时,'content'片段通过 显示FragmentTransaction#replace(int, Fragment, String),具有相同的ID但不同的标签
  5. 我确实覆盖了onSaveInstanceState(Bundle),但这并不总是由框架调用,根据文档“在许多情况下,片段可能大部分被拆除(例如当放置在没有显示 UI 的后堆栈上时),但它的状态在其拥有的活动实际需要保存其状态之前,不会被保存。”
  6. 我正在使用支持库

从上面的第5条,我猜低端设备需要在片段事务后恢复内存可能会调用Fragment#onSaveInstanceState(Bundle). 但是,在我的测试设备(Galaxy Nexus 和 Nexus 7)上,该框架不会调用该方法。所以这不是一个有效的选择。

那么,我怎样才能保留一些片段数据呢?传递给Fragment#onCreate,Fragment#onActivityCreated等的包总是null.

因此,我无法从全新的片段启动到回栈恢复。

注意:可能相关/重复的问题

4

1 回答 1

11

这似乎不对,但这是我最终的做法:

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
    }
}

有用!

  • 如果从后台堆栈返回,片段使用保存在onDestroyView
  • 如果从另一个应用程序/进程/内存不足返回,则从onSaveInstanceState
  • 如果是第一次创建,片段使用设置的参数setArguments

涵盖所有事件,并始终保留最新信息。

它实际上更复杂,它是基于 - 的,侦听器是从/interface取消/注册的。但是原理是一样的。onAttachonDetach

于 2013-06-24T11:05:48.327 回答