我对片段有一个非常奇怪的问题。我使用最新的支持库。我还使用了Google在其IOSCHED project
中使用的类似代码但我在轮换后重新创建活动时遇到问题。在销毁并再次创建活动之后,我调用了用于管理片段事务的方法(在onStart方法中)。该行只被调用一次,但它会创建片段TWICE!
这是我的活动方法:
public abstract class SinglePaneActivity extends FragmentActivity
{
@Override
protected void onStart()
{
super.onStart();
if(mFragment == null)
{
mFragment = onCreatePane();
mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));
Log.w(TAG, "Fragment creation counter = " + createCounter);
createCounter++;
getSupportFragmentManager()
.beginTransaction()
.add(R.id.root_container,mFragment)
.commit();
}
}
@Override
protected void onStop()
{
Log.i(TAG, "onStop");
if(mFragment != null)
{
getSupportFragmentManager()
.beginTransaction()
.remove(mFragment)
.commit();
mFragment = null;
}
super.onStop();
}
}
和我的日志:
--Start of application--
11-18 13:26:37.050: I/SinglePaneActivity(19040): onCreate
11-18 13:26:37.050: I/SinglePaneActivity(19040): onStart
11-18 13:26:37.055: W/SinglePaneActivity(19040): replacing fragment, counter = 1
11-18 13:26:37.075: I/MyFragment(19040): onCreate
11-18 13:26:37.110: I/MyFragment(19040): onActivityCreated
--Rotating the device--
11-18 13:26:39.600: I/SinglePaneActivity(19040): onStop
11-18 13:26:39.600: I/SinglePaneActivity(19040): onDestroy
11-18 13:26:39.605: I/MyFragment(19040): onDestroy
11-18 13:26:39.755: I/MyFragment(19040): onCreate
11-18 13:26:39.755: I/SinglePaneActivity(19040): onCreate
11-18 13:26:39.790: I/MyFragment(19040): onActivityCreated
11-18 13:26:39.800: I/SinglePaneActivity(19040): onStart
11-18 13:26:39.800: W/SinglePaneActivity(19040): replacing fragment, counter = 2
11-18 13:26:39.810: I/MyFragment(19040): onCreate
11-18 13:26:39.815: I/MyFragment(19040): onActivityCreated
--Rotating the device back--
11-18 13:36:47.060: I/SinglePaneActivity(19040): onStop
11-18 13:36:47.060: I/SinglePaneActivity(19040): onDestroy
11-18 13:36:47.060: I/MyFragment(19040): onDestroy
11-18 13:36:47.065: I/MyFragment(19040): onDestroy
11-18 13:36:47.130: I/MyFragment(19040): onCreate
11-18 13:36:47.130: I/MyFragment(19040): onCreate
11-18 13:36:47.130: I/SinglePaneActivity(19040): onCreate
11-18 13:36:47.140: I/MyFragment(19040): onActivityCreated
11-18 13:36:47.150: I/MyFragment(19040): onActivityCreated
11-18 13:36:47.150: I/SinglePaneActivity(19040): onStart
11-18 13:36:47.150: W/SinglePaneActivity(19040): replacing fragment, counter = 3
11-18 13:36:47.160: I/MyFragment(19040): onCreate
11-18 13:36:47.160: I/MyFragment(19040): onActivityCreated
--Exiting the app--
11-18 13:36:48.880: I/SinglePaneActivity(19040): onStop
11-18 13:36:48.885: I/SinglePaneActivity(19040): onDestroy
11-18 13:36:48.885: I/MyFragment(19040): onDestroy
11-18 13:36:48.890: I/MyFragment(19040): onDestroy
11-18 13:36:48.890: I/MyFragment(19040): onDestroy
因此,每次轮换后片段的数量都会增加。
旋转之后,它会在进入我的onStart方法之前恢复片段,而我的onStart方法会在相同的Frame布局容器中创建第二个相同的片段。但它在哪里恢复第一个片段?我想要它。或者我应该更改我的“if”以测试它是否已经创建?但我不知道如何确定它。看起来空测试是没用的。
我还通过add()
替换replace()
方法做了一些小的解决方法。在此之后,片段的数量不会增长,并且每个片段在新的片段创建onStart
方法之前被销毁。但是这在一些片段中造成严重问题,我在他们的onCreate方法中启动了一些后台进程...
请帮助我......我真的不知道该怎么做。非常感谢您的任何建议或想法!
答案 0 :(得分:24)
我找到了解决方案。我必须将片段管理器的代码从onStart移动到onCreate并检查null
savedInstanceState
的值。好吧,我不知道它是自动保存并从savedInstanceState
恢复的。很高兴知道!
编辑: 并且为了完全正确,即当savedInstanceState不为null时恢复片段,应该有:
if(savedInstanceState == null)
{
mFragment = onCreatePane();
mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));
getSupportFragmentManager()
.beginTransaction()
.add(R.id.root_container,mFragment)
.commit();
}
else
{
mFragment = getSupportFragmentManager().findFragmentById(R.id.root_container);
}
答案 1 :(得分:1)
我遇到了类似的问题,但是我从父片段中添加了一个子片段并看到了一个重复的子片段。我试图将其添加到父片段的onStart
中,以便我可以访问onCreate
中无法使用的父视图。因此,我没有将代码移至onCreate
,而是将其移至onActivityCreated
;该方法可以访问父视图,并且还可以访问savedInstanceState
变量以检查片段是否已经自动添加。从活动添加片段时,这不是问题,因为活动的视图在onCreate
中可用。
如果由于某种原因您需要在onStart
或其他savedInstanceState
不可用的地方添加片段,可以选择其他方式。使用问题中的原始onStart代码...
if(mFragment == null)
{
mFragment = onCreatePane();
mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));
Log.w(TAG, "Fragment creation counter = " + createCounter);
createCounter++;
getSupportFragmentManager()
.beginTransaction()
.add(R.id.root_container,mFragment)
.commit();
}
...你可以replace
而不是add
片段:
if(mFragment == null)
{
mFragment = onCreatePane();
mFragment.setArguments(Utils.intentToFragmentArguments(getIntent()));
Log.w(TAG, "Fragment creation counter = " + createCounter);
createCounter++;
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.root_container,mFragment)
.commit();
然后,如果片段已经自动添加,您的新片段将在视图中替换它。
答案 2 :(得分:-1)
或者,如果您的片段不在后台堆栈中:setRetainInstance(true);