应用程序被杀死并恢复后,如何在Activity中避免多个片段实例?

时间:2015-05-14 18:00:28

标签: android android-fragments fragmenttransaction

我有一个主屏幕的应用程序,它有2个片段(现在)和导航抽屉。目前我在启动时加载片段A(Explore)并在单击时加载片段B.从那时起,我展示并隐藏片段。它比在每次点击时重新创建片段更快,而我的片段A需要一些时间来加载。

我注意到当我去片段B并从那里去另一个活动(让它称之为活动2)并离开应用程序并等待它被杀死(或做一些疯狂的事情)比如改变设备语言,然后再回到相同的活动,它仍然在那里。当我按回去回到片段B时,有时(50%的时间)片段B被绘制在片段A上。在抽屉中单​​击片段A时,片段A看起来很好,但是在点击片段B时,有'片段A的另一个实例,在片段B的顶部。

我已经花了两天多时间解决这个问题并且无处可去。

这是我选择片段的代码:

private void selectItem(int position, boolean addExploreFragment) {
    Log.d(tag, "selectItem: " + position);

    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

    //add explore fragment - this is called on app startup, but also when the app is killed and resumed which results in 2 explore fragments

    if (addExploreFragment){

        fragmentTransaction.replace(R.id.content_frame, mExploreFragment, EXPLORE_FRAGMENT_TAG);
        Log.d(tag, "Replaced frame and added "+ mFragmentTags[position]);

    } else {
        //add fragment for the first time
        if (getSupportFragmentManager().findFragmentByTag(mFragmentTags[position]) == null && position != 0) {
            fragmentTransaction.add(R.id.content_frame, mFragments[position], mFragmentTags[position]);
            Log.d(tag, "Added Fragment: "+ mFragmentTags[position]);
        }
        //shows and hides fragments
        for (int i = 0; i < mFragments.length; i++) {
            if (i == position) {
                fragmentTransaction.show(mFragments[i]);
                Log.d(tag, "Showing Fragment: "+ mFragmentTags[i]);
            } else {
                if (getSupportFragmentManager().findFragmentByTag(mFragmentTags[i]) != null) {
                    fragmentTransaction.hide(mFragments[i]);
                    Log.d(tag, "Hid Fragment: "+ mFragmentTags[i]);
                }
            }
        }

    }

    fragmentTransaction.commit();
    //not null check for calling selectItem(0) before loading the drawer
    if (mDrawerList != null){
        mDrawerList.setItemChecked(position, true);
    }
}

我肯定知道,探索片段会被创建两次,并且两个实例的行为彼此独立(只是共享)。

我失去了下一步该怎么做。这个问题可以在低端设备上轻松复制,但在像Nexus 4(我的测试设备)这样的设备上,可以通过更改设备语言来重现该问题。

有没有人对此有任何想法?基本上如果addExploreFragment块在已经有一个exploreFragment时没有被调用,我认为这个问题可以解决,但我还是无法解决。此外,我尝试删除所有片段,然后添加exploreFragment但同样的事情发生(50%的时间)。

谢谢!对于长篇文章感到抱歉,我觉得我应该分享所有的细节。

更新:当我更改设备语言并返回活动2上的应用程序并返回主页活动时,它打开了片段B,这很好,但片段A重新创建,因为它是一个沉重的片段,系统可能会从内存中删除它。再说一遍,如果它被系统删除,它会被重新创建,但为什么在它没有被删除时重新创建它。我相信它是我的代码的一部分,在每次第二次尝试(没有关闭应用程序)这发生时,重型片段A的2个实例。出于想法。

但不应该使用fragmentTransaction.replace删除之前添加的所有片段,然后添加exploreFragment。它不是那样工作的。片段A和片段B都没有被删除。

2 个答案:

答案 0 :(得分:1)

我发现了一些新的东西而且对我来说很奇怪。当您使用fragmentTransaction.add时,上一个片段上的侦听器(如上一个片段仍处于活动状态。即使您使用fragmentTransaction.commit

也是如此

所以......我怀疑当使用 add 方法时,你实际上点击了另一个隐藏的按钮或隐藏的UI,它在前一个片段上有一个事件监听器。我当然不喜欢这样,效果可能非常混乱。是的,这发生在我身上,我暂时不理解为什么。

目前,我认为最简单的代码修复方法是使用替换方法而不是添加。 replace()使侦听器处于非活动状态。如果它有效,那么你可以做出更好/更优雅的修复。

让我知道会发生什么......

答案 1 :(得分:0)

我开始注意到你的帖子了

  

当我去片段B然后去另一个活动时

当您进行交互或启动另一个活动时,您将启动一组新的碎片。请查看此Google网页@ Fragments Lifecycle。 为了澄清我的说法,有一句话说

  

片段必须始终嵌入到活动和片段中   生命周期直接受主机活动生命周期的影响。

你至少可以阅读它的几个段落。

我不确定你的解决方案应该是什么。也许在你所拥有的两项活动之间使片段与众不同,不同和清晰。