分离不触发 onSaveInstanceState() 的片段
Posted
技术标签:
【中文标题】分离不触发 onSaveInstanceState() 的片段【英文标题】:Detaching a Fragment not triggering onSaveInstanceState() 【发布时间】:2012-08-27 17:41:31 【问题描述】:我的 android 应用程序有一个 ActionBar
,它改变了 Fragment
占用某个 FrameLayout
。我正在尝试使用onSaveInstanceState
来保存一个Fragment 在tab 改变时的状态,以便可以在onCreateView
中恢复。
问题是,onSaveInstanceState
永远不会被调用。调用了Fragment
的onDestroyView
和onCreateView
方法,但提供给onCreateView
的Bundle
仍然为空。
有人可以向我解释什么时候实际调用了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
仅在托管 Fragment
的 Activity
被销毁并且您有可能返回相同的活动并且片段仍添加到 FragmentManager
时才被调用。最常见的情况是屏幕旋转。
我认为您的Fragment
也需要在onCreate
中执行setRetainInstance(true)
。不过不太确定这一点。
例如,当您按下主页按钮时,您还应该看到此方法被调用。这将破坏活动,但您可以使用任务列表返回到它。
如果您只是detach()
片段,您只需向FragmentManager
索取即可。
你应该看看两个例子:
ActionBar
FragmentTabs 和 TabHost
FragmentTabs
TabHost
示例使用
ft.add(containerId, fragment, tag);
// later
fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
要查找以前添加的Fragment
s 的实例,直到您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() 的片段的主要内容,如果未能解决你的问题,请参考以下文章
为啥按“返回”按钮后不调用 onSaveInstanceState()?
Gitlab-ci:如果 MR 存在则触发 merge_request 分离管道,如果不存在则触发源分支管道。这两条管道不应同时运行