【问题标题】:Android Fragment View State Loss When Using FragmentTransaction.replace()使用 FragmentTransaction.replace() 时的 Android 片段视图状态丢失
【发布时间】:2013-04-12 17:39:12
【问题描述】:

我遇到了一个很大的问题,我不太明白发生了什么。我正在开发一个使用 Fragments(来自支持库)的应用程序,并且正在使用 FragmentTransaction.replace() 将新的 Fragments 放在后堆栈上并替换旧的。代码如下:

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = ft.beginTransaction();
// Animations in my res/anim folder
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.fragment_container, newFragment, tag);
ft.addToBackStack(null);
ft.commit();

这成功替换了我的片段。我的问题如下。在一个片段中,我有一个根据用户输入构建的项目列表。现在,当用户单击下一步然后单击后退按钮(返回列表)时,列表为空,因为视图已被破坏。现在,我注意到以下几点:

  1. onSaveInstanceState 未被调用。我相信这是因为只有在父 Activity 告诉它时才会调用它。根据文档:“在许多情况下,片段可能大部分被拆除(例如,当放置在没有显示 UI 的后台堆栈时),但在其拥有的活动实际需要保存其状态之前,它的状态不会被保存."。显然,对 FragmentTransaction 执行替换并不是其中之一。有人对此有确认或更好的解释吗?
  2. setOnRetainInstanceState(true) 在这种情况下没有帮助。同样,我相信这与文档中的信息有关:“控制是否在 Activity 重新创建期间保留片段实例(例如从配置更改中)”。我没有在重新创建活动时执行任何操作,所以这没有用。

所以,我想我的主要问题是:有没有办法在使用replace 时保留视图状态(只保留片段)?有FragmentTransaction.add(),但也有一些问题。一种是没有执行退出动画,因此动画不正确。另一个是旧片段(被置于不可见状态的片段)仍然可以点击的新片段。例如,如果我有一个 ListFragment,并且我通过使用 add 在其上放置一个内容片段,我仍然可以单击 ListFragment 中的列表项。

【问题讨论】:

    标签: android android-fragments android-fragmentactivity android-lifecycle


    【解决方案1】:

    无法看到您的片段代码,这有点猜测,但过去我遇到过同样的问题,我发现在@987654322 中重置您的ListFragment 中的适配器@ 似乎可以解决问题。

    public void onViewStateRestored (Bundle savedInstanceState)
    {
        super.onViewStateRestored (savedInstanceState);
        setListAdapter(new ArrayAdapter(Activity, R.layout.nav_item, objects));
    }
    

    考虑到文档指出此方法在onActivityCreated 之后但在onStart 之前调用,这很奇怪。但它似乎在其他时间也被调用,因为当最近的片段事务从返回堆栈中弹出时,此方法在显示先前替换的片段之前被调用。拥有片段的活动没有以任何方式暂停或隐藏,因此根据文档,不应调用onViewStateRestored,因为仅修改了片段。但这似乎仍然有效。

    【讨论】:

      【解决方案2】:

      听起来您只需要确保已正确实现 onCreateView 和 onDestroyView。您所描述的情况似乎表明,当列表片段被放在后台堆栈(作为替换事务的结果)时,Android 正在调用 onDestroyView 以释放一些资源。但是,它显然没有破坏列表片段,因为当您点击返回时,您将返回片段的相同实例。

      假设这一切都是真的,那么当用户点击返回时,Android 将调用 onCreateView。您存储在片段实例变量中的任何状态都应该仍然存在,您需要做的就是重新填充视图...也许在 ListView 上设置适配器或其他任何东西。

      还要确保您的 onSaveInstanceState() 回调确实保存了重建视图所需的任何实例状态。这样,如果 Fragment 确实被完全销毁,FragmentManager 可以在稍后需要重新创建该 Fragment 时恢复状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多