回栈事务后如何持久化分片数据?
Posted
技术标签:
【中文标题】回栈事务后如何持久化分片数据?【英文标题】:How to persist fragment data after backstack transactions? 【发布时间】:2013-06-19 14:06:51 【问题描述】:我有一个活动,包含片段“列表”,单击其中一个项目时,它会将自身替换为“内容”片段。当用户使用后退按钮时,他会再次被带到“列表”片段。 问题在于,无论我如何尝试持久化数据,片段都处于默认状态。
事实:
-
两个片段都是通过
public static TheFragment newInstance(Bundle args)
、setArguments(args)
和Bundle args = getArguments()
创建的
两个片段位于同一级别,直接位于父活动的FrameLayout
内(即不是嵌套片段)
我不想打电话给setRetainInstance
,因为我的活动是一个主/细节流,它在大屏幕上有一个2 窗格布局。 7" 平板电脑有 1 个纵向窗格和 2 个横向窗格。如果我保留“列表”片段实例,它会(我认为)屏幕旋转搞砸
当用户点击'list'片段中的某一项时,'content'片段通过FragmentTransaction#replace(int, Fragment, String)
显示,ID相同,标签不同
我确实覆盖了onSaveInstanceState(Bundle)
,但这并不是由框架总是调用的,如per the doc:“在很多情况下,片段可能大部分被拆除(例如就像放置在没有显示 UI 的后堆栈上时一样),但在其拥有的 Activity 实际需要保存其状态之前,它的状态不会被保存。"
我正在使用支持库
从上面的第5条,我猜低端设备需要在片段事务后恢复内存可能会调用Fragment#onSaveInstanceState(Bundle)
。但是,在我的测试设备(Galaxy Nexus 和 Nexus 7)上,该框架不会调用该方法。所以这不是一个有效的选择。
那么,我怎样才能保留一些片段数据呢?传递给Fragment#onCreate
、Fragment#onActivityCreated
等的包总是null
。
因此,我无法从全新的片段启动到返回堆栈恢复。
注意:可能related/duplicate question
【问题讨论】:
现在我唯一的选择是:isFromBackStack = getActivity().getSupportFragmentManager().getBackStackEntryCount() > 0
。我想要一些更清洁的东西,这对我来说就像一个黑客。另外,我没有从前一个片段实例中得到Bundle
。
【参考方案1】:
这似乎不对,但这是我最终的做法:
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
有效!
如果从backstack返回,fragment使用onDestroyView
中保存的参数
如果从另一个应用程序/进程/内存不足返回,该片段将从onSaveInstanceState
恢复
如果是第一次创建,分片使用setArguments
中设置的参数
涵盖所有事件,并始终保留最新信息。
实际上更复杂,它是基于interface
的,监听器是从onAttach
/onDetach
取消/注册的。但原理是一样的。
【讨论】:
哇。我只是在学习 android,所以我怀疑我错过了一些东西。也许我应该读一本书。我无法让数据在片段的整个生命周期内持续存在。但这可以解决问题。谢谢 您可以在删除/替换之前使用 FragmentManager 的 saveFragmentInstanceState() 来代替在 onDestroyView 中为 backstack 情况保存状态。这将调用 onSaveInstanceState()。这允许您将状态持久性代码保留在一个位置。 我有一个类似的方法,我需要保存以前在替换fragment
时加载的列表。你知道这是否会导致任何内存问题吗?
将它保存在活动中对我来说似乎不是一个好主意。活动总是被逻辑阻塞。以上是关于回栈事务后如何持久化分片数据?的主要内容,如果未能解决你的问题,请参考以下文章