Android 如何在backstack事务之后持久化片段数据?

Android 如何在backstack事务之后持久化片段数据?,android,android-fragments,back-stack,Android,Android Fragments,Back Stack,我有一个活动,包含片段“列表”,点击其中一个项目后,它将自身替换为“内容”片段。当用户使用后退按钮时,他将再次进入“列表”片段。 问题是,无论我如何尝试持久化数据,片段都处于默认状态 事实: 这两个片段都是通过片段newInstance(Bundle args)、setArguments(args)和Bundle args=getArguments()创建的 两个片段位于同一级别,直接位于父活动的FrameLayout中(即,不是嵌套片段) 我不想调用setRetainInstance,因为我的

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

事实:

  • 这两个片段都是通过片段newInstance(Bundle args)、
    setArguments(args)
    Bundle args=getArguments()创建的
  • 两个片段位于同一级别,直接位于父活动的
    FrameLayout
    中(即,不是嵌套片段)
  • 我不想调用
    setRetainInstance
    ,因为我的活动是一个主/详细流程,在较大的屏幕上有两个窗格的布局。7英寸平板电脑有1个纵向窗格和2个横向窗格。如果我保留“列表”片段实例,它(我认为)会因为屏幕旋转而把事情搞砸
  • 当用户单击“列表”片段中的项目时,“内容”片段将通过
    FragmentTransaction#replace(int,fragment,String)
    显示,ID相同,但标记不同
  • 我确实重写了saveInstanceState(Bundle),但框架并不总是调用它,因为:“在很多情况下,一个片段可能会大部分被拆下(例如,当放在后堆栈上时,没有显示UI),但在其所属活动实际需要保存其状态之前,不会保存其状态。”
  • 我正在使用支持库
  • 从上面的项目符号5中,我猜需要在片段事务后恢复内存的低端设备可能会调用
    fragment\onSaveInstanceState(Bundle)
    。但是,在我的测试设备(Galaxy Nexus和Nexus 7)上,框架不会调用该方法。因此这不是一个有效的选项

    那么,如何保留一些片段数据呢?传递给
    fragment#onCreate
    fragment#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
        }
    }
    
    它起作用了

    • 如果从backback返回,片段将使用保存在
      onDestroyView
    • 如果从另一个应用程序/进程/内存不足返回,则从
      onSaveInstanceState
    • 如果是第一次创建,片段将使用
      setArguments
    所有的事件都会被报道,最新的信息总是被保存


    实际上更复杂,它是基于
    接口的,监听器是从
    onAttach
    /
    onDetach
    取消注册的。但是原理是一样的。

    现在我唯一的选择是:
    是fromBackstack=getActivity().getSupportFragmentManager().getBackStackEntryCount()>0
    。我想要更干净的东西,这让我感觉像是黑客攻击。而且,我没有从上一个片段实例中获得
    捆绑包。哇。我只是在学习android,所以我怀疑我遗漏了什么。也许我应该读一本书。我无法在片段的整个生命周期内获得数据。但这就是诀窍。谢谢您,在删除/替换FragmentManager的saveFragmentInstanceState()之前,您可以使用FragmentManager的saveFragmentInstanceState()将状态保存在onDestroyView中,而不是将状态保存在backstack案例中。这将调用onSaveInstanceState()。这允许您一次性保存状态持久性代码。我有一种类似的方法,需要保存以前在替换
    片段时加载的列表。您知道这是否会导致内存问题吗?将其保存在“活动”中似乎不是一个好主意。活动总是被逻辑阻塞。