我有一个活动,包含片段"list",单击其中一个项目后,它将替换为"content"片段。当用户使用后退按钮时,他将再次进入"列表"片段
问题是,无论我尝试如何持久化数据,片段都处于默认状态。
事实:
- 这两个片段都是通过
public static TheFragment newInstance(Bundle args)
、setArguments(args)
和Bundle args = getArguments()
创建的 - 两个片段位于同一级别,直接位于父活动的
FrameLayout
内部(即,不是嵌套片段) - 我不想调用
setRetainInstance
,因为我的活动是一个主/细节流,在较大的屏幕上有两个窗格布局。7"平板电脑有1个纵向窗格和2个横向窗格。如果我保留"列表"片段实例,它会(我认为)通过屏幕旋转来搞砸事情 - 当用户单击"列表"片段中的项目时,"内容"片段将通过
FragmentTransaction#replace(int, Fragment, String)
显示,具有相同的ID但具有不同的标记 - 我确实覆盖了
onSaveInstanceState(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
}
}
它有效!
- 如果从后台返回,则片段使用保存在
onDestroyView
中的参数 - 如果从另一个应用程序/进程/内存不足返回,则从
onSaveInstanceState
恢复片段 - 如果是第一次创建,则片段将使用
setArguments
中设置的参数
所有活动都涵盖在内,并始终保持最新的信息。
它实际上更复杂,它是基于interface
的,侦听器是从onAttach
/onDetach
取消/注册的。但原则是一样的。