6

我的APP确实有多个片段和活动,这些活动中的大多数都持有不同的片段,这是为了让我的组件易于重用。当我将其他活动加载到活动堆栈时,我遇到了一个问题。

案例
启动ActivityA-->ActivityB-->ActivityC

所有这些活动都包含不同的片段,但问题是何时从其中的片段ActivityB启动时不会被调用,尽管 onStop 被调用。ActivityAActivityA onDestroyView

当我继续向堆栈应用程序添加太多活动时,我的应用程序允许从一个到另一个进行无限次数的导航,逐渐引发 OOM 异常。

在下面找到我用来将片段添加到片段回栈的代码。

final android.support.v4.app.FragmentTransaction ft =
                fragmentManager.beginTransaction();
if(transaction.mInAnimation != FragmentTransaction.FRAGMENT_NO_ANIMATION &&
                transaction.mOutAnimation != FragmentTransaction.FRAGMENT_NO_ANIMATION) { 
    ft.setCustomAnimations(transaction.mInAnimation, transaction.mOutAnimation);
}
String tag;
if(transaction.isRoot){
   clearFragmentStack();
   tag = "0";
}else {
   tag = fragmentManager.getBackStackEntryCount() + "";
}
final AtomicFragment fragment = transaction.compile();
ft.replace(transaction.mFrameId, fragment,  tag);
ft.addToBackStack(tag);
ft.commit();
4

4 回答 4

7

因此,您的问题似乎是“当您继续向堆栈应用程序添加太多活动时,会逐渐引发 OOM 异常”,并且您认为原因可能是onDestroyView()在切换活动时未在顶部 Fragment 上调用。

OnDestroyView()

首先,当您从 Activity1 转到 Activity2 时,很可能没有在 Activity1 中调用您的 Fragment,因为您在启动 Activity2 后onDestroyView()没有在 Activity1 中调用。finish()

这意味着您的 Activity1 在活动后台堆栈中是活动的并且很好,但已停止(即 onStop 调用)。由于 Activity1 是活着的,所以它的 backstack & Fragments 也是活着的。Activity1 的 backstack 顶部的片段也将被停止。所以基本上,Activity1 的状态类似于您使用 Home 按钮将应用程序发送到后台时进入的状态。

在其他情况下,当在 Fragment backstackonDestroyView()中添加另一个 Fragment 时在 Fragment 上调用它。但是,它对活动回栈/活动任务一无所知

如果您想清除片段的视图,您可以手动执行(即fragmentManager.popbackstack(),或beginTrasaction.remove(...)),或者您可以在启动 Activity2(即调用finish())后关闭 Activity1 - 这也将释放您的内存并调用onDestroyView()Activity1 中的顶部片段。

内存不足异常

...当我继续向堆栈应用程序添加太多活动时,会逐渐引发 OOM 异常。

OOM 崩溃的最可能的原因是您的内存中有太多的 Activity 实例,而onDestroyView()不是在某些片段上没有调用。我还假设您有同一个Activity 的多个实例。

在声明您的活动时,请考虑使用android:launchMode="singleTask"( referenceAndroidManifest.xml ) 。这可确保您在给定任务中只有某个 Activity 的单个实例。如果它是由同一活动的太多实例引起的,这本身应该可以解决您的 OutOfMemory问题

这种方法本身将意味着您需要进行某些额外的处理,以将重用活动的 UI/状态重置为“干净”的。幸运的是,您可以依靠onNewIntent(...)( reference ) 来检测何时需要这样做。

稍后编辑:内存监视器

关于查找 OutOfMemory 错误原因:请使用Android 内存监视器查找内存泄漏。我发现内存泄漏是令人讨厌的小恶魔,与(知情的)猜测相比,从一开始就使用内存监视器总是更好。

在您的情况下,在使用您的应用程序一段时间后,在执行一些活动切换后,您需要查看内存中是否有特定活动的多个实例(例如 Activity1)。

基本上,您需要寻找类似的东西: 在此处输入图像描述

请记住在进行堆转储之前强制垃圾收集器几次(仅一次是不够的)。这是为了确保在某些时候会被垃圾收集的引用不会出现在您的转储中。

希望这可以帮助

于 2018-04-06T07:27:51.983 回答
1

由于您允许从一个活动无限次导航到另一个活动,因此每次启动活动时都会创建一个新的活动实例。要阻止它被多次创建,请只创建一次活动,以便只创建该活动的一个实例。为此,请将此行添加到您的清单文件中的标记中,如下所示:

<activity android:name=".MainActivity"
        android:launchMode="singleTop"/>
于 2018-04-06T07:30:24.907 回答
1

我注意到的简单解决方案是

onDestroy()

将被调用而不是 onDestroyView() 以便您可以使用 onDestroy()

于 2018-04-09T20:29:20.293 回答
-4

试试这个代码并将这个代码添加到你的片段中

@Override
public void onDestroy() {
    super.onDestroy();
}
@Override
public void onPause() {
    super.onPause();
}
@Override
public void onResume() {
    super.onResume();
}
@Override
public void onStop() {
    super.onStop();
}
于 2018-04-09T10:15:38.603 回答