12

我对片段有一个非常奇怪的问题。我使用最新的支持库。我也使用 Google 在他们的IOSCHED 项目中使用的类似代码

但是我在旋转后重新创建活动时遇到问题。在销毁并再次创建活动后,我调用管理片段事务的方法(在 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 布局容器中创建第二个相同的片段。但是它在哪里恢复了第一个片段?我想禁止它。或者我应该改变我的“如果”来测试它是否已经创建?但我不知道如何确定它。看起来空测试没用。

add()我还通过将方法替换为replace(). 之后,片段的数量不会增加,并且每个片段在onStart创建新片段之前被销毁。但这在一些片段中造成了严重的问题,我在他们的 onCreate 方法中启动了一些后台进程......

请帮帮我...我真的不知道该怎么办。非常感谢您的任何建议或想法!

4

3 回答 3

24

好吧,我找到了解决方案。我不得不将带有片段管理器的代码从 onStart 移动到 onCreate 并检查null. savedInstanceState好吧,我不知道它是savedInstanceState自动保存和恢复的。很高兴知道!

编辑:要做到完全正确,即当 savedInstanceState 不为空时恢复片段,应该有:

    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);
    }
于 2011-11-21T13:04:33.727 回答
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();

然后,如果片段已经自动添加,您的新片段将在视图中替换它。

于 2014-09-17T04:08:05.843 回答
-1

或者,如果您的片段不在后堆栈中:setRetainInstance(true);

于 2012-04-04T16:00:25.483 回答