分离不触发 onSaveInstanceState() 的片段

Posted

技术标签:

【中文标题】分离不触发 onSaveInstanceState() 的片段【英文标题】:Detaching a Fragment not triggering onSaveInstanceState() 【发布时间】:2012-08-27 17:41:31 【问题描述】:

我的 android 应用程序有一个 ActionBar,它改变了 Fragment 占用某个 FrameLayout。我正在尝试使用onSaveInstanceState 来保存一个Fragment 在tab 改变时的状态,以便可以在onCreateView 中恢复。

问题是,onSaveInstanceState 永远不会被调用。调用了FragmentonDestroyViewonCreateView 方法,但提供给onCreateViewBundle 仍然为空。

有人可以向我解释什么时候实际调用了onSaveInstanceState,我如何确保在切换选项卡时调用它,或者当Fragment 分离和重新时保存和恢复状态的最佳实践- 附上?

片段:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) 
    View view = inflater.inflate(R.layout.event_log, container, false);

    // Retrieve saved state
    if (savedInstanceState != null)
        System.out.println("log retrieved");
     else 
        System.out.println("log null");
    

    return view;


@Override
public void onSaveInstanceState(Bundle outState) 
    System.out.println("log saved");
    super.onSaveInstanceState(outState);
    // more code

活动:

/**
 * Detach the current Fragment, because another one is being attached.
 */
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) 
    if (tab.getText().equals(getString(R.string.tab_events)))
        if (frEventLog != null) 
            ft.detach(frEventLog);
    

【问题讨论】:

***.com/questions/8503629/…的可能副本 【参考方案1】:

Fragment#onSaveInstanceState 仅在托管 FragmentActivity 被销毁并且您有可能返回相同的活动并且片段仍添加到 FragmentManager 时才被调用。最常见的情况是屏幕旋转。

我认为您的Fragment 也需要在onCreate 中执行setRetainInstance(true)。不过不太确定这一点。

例如,当您按下主页按钮时,您还应该看到此方法被调用。这将破坏活动,但您可以使用任务列表返回到它。

如果您只是detach() 片段,您只需向FragmentManager 索取即可。

你应该看看两个例子:

ActionBar FragmentTabs 和 TabHost FragmentTabs

TabHost 示例使用

ft.add(containerId, fragment, tag);
// later
fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);

要查找以前添加的Fragments 的实例,直到您remove()Fragment 为止


关于onCreateView / onDestroyView:一旦片段被分离就会调用它,因为下次附加它时需要创建一个新的View。请注意,Fragment#onDetached() 不会在您 detach() 片段时调用,因为它仍然附加到 Activity。它仅与视图层次结构分离。


还有另一个很好的例子,关于如何在 Android 培训中保留片段状态/如何使用片段来保留状态 - Caching Bitmaps。

该示例缺少关键行:

public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) 
    RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
    if (fragment == null) 
        fragment = new RetainFragment();
        fm.beginTransaction().add(fragment, TAG).commit(); // << add this
    
    return fragment;

【讨论】:

感谢您的回复。我的印象是使用 setRetainInstance(true) 会占用大量内存,因为这意味着存储选项卡而不是销毁和重新创建它们,但我会试一试。我必须通过 FragmentManager 获取我的 Fragment 还是可以在字段中保留对它们的引用? 您根本不需要参考。 FragmentManager 对它们有引用,但如果您不添加内存泄漏,则可以添加一个。记忆强度取决于你在片段中使用了多少,如果你做得对,它可能接近于 0 我想在您的第一个示例的帮助下,我现在已经对此进行了排序。我的问题实际上是我在 Fragment 的 onActivityCreated() 方法中有一些代码,它实际上是在重置它,因为我没有意识到这个方法会运行不止一次。 是的,活动会在配置更改(如轮换)时重新创建,您会再次被调用。获得正确的生命周期是很棘手的:/OnCreate 将是一个只应该被调用一次的地方。

以上是关于分离不触发 onSaveInstanceState() 的片段的主要内容,如果未能解决你的问题,请参考以下文章

onsavelnstancestate有啥作用?如何使用

activity状态保存与恢复

为啥按“返回”按钮后不调用 onSaveInstanceState()?

Gitlab-ci:如果 MR 存在则触发 merge_request 分离管道,如果不存在则触发源分支管道。这两条管道不应同时运行

Android Jetpack -- ViewModel篇

出现异常“IllegalStateException:onSaveInstanceState 后无法执行此操作”