如何在后台事务后持久化碎片数据



我有一个活动,包含片段"list",单击其中一个项目后,它将替换为"content"片段。当用户使用后退按钮时,他将再次进入"列表"片段
问题是,无论我尝试如何持久化数据,片段都处于默认状态。

事实:

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

从上面的项目符号5中,我猜在碎片事务后需要恢复内存的低端设备可能会调用Fragment#onSaveInstanceState(Bundle)。然而,在我的测试设备(Galaxy Nexus和Nexus 7)上,框架并没有调用这种方法。所以这不是一个有效的选择。

那么,如何保留一些片段数据呢?传递到Fragment#onCreateFragment#onActivityCreated等的束总是null

因此,从全新的碎片发布到后堆栈恢复,我无法做出任何改变。

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

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

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的,侦听器是从onAttach/onDetach取消/注册的。但原则是一样的。

最新更新