我们使用的是Fragments,我们不需要它们在重新创建Activity时自动恢复。 但是每次调用
Activity::onCreate(Bundle savedInstanceState)
-> super.onCreate(savedInstanceState)
时,Android 都会恢复 Fragment,即使我们对这些 Fragment 使用 setRetainInstance(false) 。
而且,在那些
Fragments
Fragment.performCreateView()
中,直接调用而不经过 Fragment::onAttach()
等等。另外,恢复后的某些字段为空Fragment
...
有人知道如何防止Android恢复碎片吗?
附注我们知道,如果要为配置更改重新创建 Activity,可以通过添加到清单 a
ndroid:configChanges="orientation|screenSize|screenLayout
来完成。但是在自动内存清理的情况下重新创建活动怎么样?
我们通过添加活动来完成:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
它会抑制活动创建/重新创建周期中保存的任何数据,并避免片段自动重新创建。
@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;
}
我遇到了
TransactionTooLargeException
的问题。值得庆幸的是,在使用 tolargetool 后,我发现片段(android:support:fragments)一直在内存中,并且事务变得太大。所以最后我做到了,效果很好。
@Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("android:support:fragments", null);
}
编辑:我将其添加到活动中。就我而言,我有一个 Activity 应用程序和多个片段。
那些在使用已接受答案中描述的方法时使用 ViewPager 获得 NPE 的人,请覆盖
ViewPager.onRestoreInstanceState(Parcelable state)
方法及调用
super.onRestoreInstanceState(null);
相反。
我删除了Activity的onCreate中的碎片。
对于带有
ViewPager
的应用程序,我会在创建之前删除 onCreate()
中的片段。
基于此线程:从容器中删除所有碎片,我们有:
FragmentManager fm = getSupportFragmentManager();
for (Fragment fragment: fm.getFragments()) {
fm.beginTransaction().remove(fragment).commitNow();
}
将此用于 androidx
override fun onCreate(savedInstanceState: Bundle?) {
preventFragmentRecreation()
super.onCreate(savedInstanceState)
}
private fun preventFragmentRecreation() {
supportFragmentManager.addFragmentOnAttachListener { _, _ ->
savedStateRegistry.unregisterSavedStateProvider("android:support:fragments")
}
}
这对我有用
@Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.remove("androidx.lifecycle.BundlableSavedStateRegistry.key");
}
如上所述,
androidx:support:fragments
位于AndroidX上的androidx.lifecycle.BundlableSavedStateRegistry.key
下,要从捆绑包中完全删除片段,您可以清理捆绑包和嵌套捆绑包:
override fun onCreate(savedInstanceState: Bundle?) {
SplashScreen.show(this)
/**
* Remove fragments from saved state to prevent crashes
*/
if (savedInstanceState != null) {
savedInstanceState.remove("android:support:fragments")
savedInstanceState.remove("android:fragments")
val bundlableSavedStateRegistry = savedInstanceState.getBundle("androidx.lifecycle.BundlableSavedStateRegistry.key");
bundlableSavedStateRegistry?.remove("android:support:fragments")
savedInstanceState.putBundle("androidx.lifecycle.BundlableSavedStateRegistry.key", bundlableSavedStateRegistry)
}
super.onCreate(savedInstanceState)
此修复了https://github.com/software-mansion/react-native-screens/issues/17在
React Native 0.75.3
/Android 14
视图层次结构不会自动恢复。因此,在
Fragment.onCreateView()
或 Activity.onCreate()
中,您必须恢复所有视图(从 xml 或以编程方式)。每个包含片段的 ViewGroup 必须具有与第一次创建它时相同的 ID。一旦创建了视图层次结构,Android 就会恢复所有片段,并根据 ID 将它们的视图放入正确的 ViewGroup 中。假设 Android 记住了片段所在的 ViewGroup 的 ID。这种情况发生在 onCreateView()
和 onStart()
之间。