防止Android中的碎片恢复

42
我们正在使用Fragment,但当Activity重新创建时,我们不希望它们自动恢复。 但是,每次调用Activity::onCreate(Bundle savedInstanceState) -> super.onCreate(savedInstanceState)时,Android都会还原Fragment,即使我们对这些Fragment使用了setRetainInstance(false)。
此外,在那些Fragments中,Fragment.performCreateView()直接调用,而不经过Fragment::onAttach()等流程。此外,一些字段在还原的Fragment中是null ...
有人知道如何防止Android恢复Fragments吗?
P.S. 我们知道,在为配置更改重新创建Activity的情况下,可以通过向清单添加android:configChanges="orientation|screenSize|screenLayout来实现。但在自动内存清理的情况下重新创建活动怎么办?
9个回答

57

我们通过添加活动来完成:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
}

它在创建/重新创建Activity时抑制任何保存的数据,并避免片段自动重新创建。


1
简单而又有效。这真的拯救了我在当前糟糕的设计中(每个屏幕一个Activity应用程序+1个Fragment)的困境。 - momo
如果代码片段涉及到用户界面,那么您不觉得这会影响用户体验吗? - Muhammad Babar
4
这个方法非常有效,但我希望有更简洁的方式来实现这个目标... - jenzz
2
这使得我的带有ViewPager的应用程序崩溃了。 - Wayne
1
@momo,这是我正在使用的相同设计 - 你知道更好的方法吗? - Martin Konecny
显示剩余4条评论

24

@goRGon的答案对我非常有用,但这种使用方式会在重新创建后需要转发更多信息到您的活动时导致严重问题。

这里是改进版,只删除“片段”,但保留其他所有参数。

从束中删除的ID是android.support.v4.app.FragmentActivity类的一部分,作为FRAGMENTS_TAG字段。它可能随时间而变化,但不会出现意外情况。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(createBundleNoFragmentRestore(savedInstanceState));
}

/**
 * Improve bundle to prevent restoring of fragments.
 * @param bundle bundle container
 * @return improved bundle with removed "fragments parcelable"
 */
private static Bundle createBundleNoFragmentRestore(Bundle bundle) {
    if (bundle != null) {
        bundle.remove("android:support:fragments");
    }
    return bundle;
}

太棒了。正是我在寻找的。 - Bolein95
2
你也可以在 onSaveInstanceState() 中使用相同的技巧。这样可以避免首先将 Fragment 信息持久化。 - greeble31

4

我遇到了TransactionTooLargeException的问题。幸运的是,在使用tolargetool之后,我发现片段(android:support:fragments)一直在内存中,并且事务变得太大。最终,我做了这个,它非常有效。

@Override
public void onSaveInstanceState(final Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("android:support:fragments", null);
}

编辑:我将它添加到了Activity中。在我的情况下,我有一个单一的Activity应用程序和多个Fragment。


抱歉,您是将它添加到您的活动还是片段中了? - Nokuap
@Nokuap 我已将它添加到 Activity 中。在我的情况下,我有一个单一的 Activity 应用程序和多个 Fragments。 - MontDeska

3

如果使用接受答案中描述的方法时,ViewPager出现NPE,请覆盖

ViewPager.onRestoreInstanceState(Parcelable state)

方法并调用

super.onRestoreInstanceState(null);

即可。


这种方法不适用于ViewPager2。 - Sirop4ik

1

我在Activity的onCreate方法中移除了一些片段。


0

对于一个带有 ViewPager 的应用程序,我在 onCreate() 中删除了它们的创建之前的片段。

根据这个线程:从容器中删除所有片段,我们有:

FragmentManager fm = getSupportFragmentManager();
for (Fragment fragment: fm.getFragments()) {
  fm.beginTransaction().remove(fragment).commitNow();
}

如果配置了片段以进行恢复,则会导致异常。 - htafoya
1
你如何配置它们以便恢复? - mortalis

0

这对我有用

@Override
public void onSaveInstanceState(final Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.remove("androidx.lifecycle.BundlableSavedStateRegistry.key");
}
    

0
请使用此代码适配androidx。
override fun onCreate(savedInstanceState: Bundle?) {
   preventFragmentRecreation()
   super.onCreate(savedInstanceState) 
}

private fun preventFragmentRecreation() {
   supportFragmentManager.addFragmentOnAttachListener { _, _ ->
            savedStateRegistry.unregisterSavedStateProvider("android:support:fragments")
        }
}

-1

视图层次结构不会自动恢复。因此,在Fragment.onCreateView()Activity.onCreate()中,您必须恢复所有视图(从xml或以编程方式)。每个包含片段的ViewGroup必须与第一次创建它时具有相同的ID。一旦创建了视图层次结构,Android将恢复所有片段并将它们的视图放置在正确的ViewGroup中,这要归功于ID。假设Android记住了片段所在的ViewGroup的ID。这发生在onCreateView()onStart()之间的某个地方。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接