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

Ben*_*fez 9 android android-fragments back-stack

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

事实:

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

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

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

因此,我无法从全新的片段启动到后台堆栈恢复有所作为.

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

Ben*_*fez 10

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

public class MyActivity extends FragmentActivity {
    private Bundle mMainFragmentArgs;

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

    public Bundle getSavedMainFragmentState() {
        return mMainFragmentArgs;
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

在主要片段中:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

有用!

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

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

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