【发布时间】:2017-08-25 15:26:56
【问题描述】:
我有一个内存不足的问题。
我有一套跨应用程序的活动和一个类。
我在每个活动的清单中将launchMode 设置为SingleTop,并将noHistory 设置为true。
我也设置了android: largeHeap = "true"
我称之为 A、B、C、D、E 的一项主要活动和五项其他活动
A、B、C 总是在 HEAP 中显示单个实例,但 D 和 E 每次新 Intent 及其 startActivity 都会增加实例数
C 使用 D 和 E 中也使用的相同对象(listview、hashmap、simpleAdapter)
发生这种情况:
主启动,然后启动C,C调用D和D调用E返回C。C总是有一个实例,而D和E每次占用1MB来指示它们的实例,最终导致Oom叠加 174Mb可用为我的应用程序。
对于我运行此代码的所有活动,例如从 activityB、startC、activityC。
Intent activityC = new Intent (getBaseContext, activityC.class); // Try too getApplicationContext, activityC.this but instances remain anyway.
activityC.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP); // I try too SINGLE_TOP, NEW_TASK, CLEAR_TASK same result
Finish (); // I also tried to call finish () after startActivity () with the same result
startActivity (activityC);
这一切都一文不值。
我还使用freeMemory() 函数调用每个活动的onDestroy(),但不管有没有变化
Public void freeMemory () {
System.runFinalization ();
Runtime.getRuntime (). Gc ();
System.gc ();
}
我已经尝试实现onNewIntent,但我从来没有得到它。
在 D 和 E onDestroy 中,我尝试将在 onCreate() 中创建的所有对象(私有)设置为 null,但未成功。
目前我正在尝试使用华硕和 Android 5.02 平板电脑。
不要使用 Handler、Timer 或 AsyncTask。
我做了多少努力(我真的尝试了很多)A、B、C 总是在 HEAP 中显示单个实例,而 D 和 E
我还创建了一个演示来尝试解决问题,但我没有得到结果。在 SINGLE_TOP 演示中,您可以按预期工作,并为每个活动保留一个实例,超过其重复次数。
什么可以保留新实例?
清单:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".TEST"
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@drawable/logo"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ActivityA"
android:hardwareAccelerated="false"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ActivityE"
android:enabled="true"
android:hardwareAccelerated="false"
android:label="@string/app_name"
android:launchMode="singleTop"
android:noHistory="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
<activity
android:name=".ActivityD"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:launchMode="singleTop"
android:noHistory="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ActivityC"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:launchMode="singleTop"
android:noHistory="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ActivityB"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:noHistory="true"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".TempActivity"
android:launchMode="singleTop"
android:noHistory="true"
/>
</application>
</manifest>
我注意到当你从一个活动切换到另一个 logcat 时告诉我: 08-26 08:22:33.607 905-5207 /? W / ActivityManager: startActivity 从完成 ActivityRecord {6d2eb11 u0 danielezampieri.TEST / .ActivityC t472 f} 中调用;强制 Intent.FLAG_ACTIVITY_NEW_TASK 用于: Intent {flg = 0x24020000 cmp = danielezampieri.TEST / .ActivityD} 因为?这是什么意思?难道是因为ActivityC生成了多个实例?
但是我在startactivity之后注释了finish()方法,只有上面提到的activity显示了多个实例。
更新!! 我把注意力集中在产生问题的地方。无论如何感谢您的建议。 在activityC(显示多个实例并占用无用内存的那个)中,我有两个扩展Dialog的类,在活动的oncreate中创建它们
newmydialog1 = New mydialog1 (this)
newmydialog1 = New mydialog2 (this)
然后我打电话
newmydialog1.show
在 mydialog1 中有一个按钮正在运行
newmydialog2.show
如果我运行 mydialog2,除非我按下运行 mydialog2 的按钮,否则我不会创建 activityC 的多个实例,这里是 activityC 上的内存泄漏,它相信每个创建的实例。 我尝试调用 newmydialog2.cancel/dismiss,然后在 mydialog1 的 cancel () 之前将 newmydialog2 设置为 null,但没有。 我还能做什么?
【问题讨论】:
-
请发布您的清单
-
您的 D 和 E 实例没有消失的原因也可能是因为某些东西持有对它们的引用。要检查这一点,请运行您的应用程序,从 C 到 D 再到 E 并返回几次。然后进行堆转储以查看堆中有多少个 C、D 和 E 实例。同时执行
adb shell dumpsys activity activities并查看任务中的活动列表。 -
我建议实施 LeakCanary 来帮助追踪您的内存泄漏:github.com/square/leakcanary。此外,如果您运行“lint”Gradle 任务,您是否会收到将 Context 值存储在成员/静态变量中的任何警告?我的猜测是 Context 变量在某处被存储为硬引用,这导致活动没有被垃圾收集。
-
另外,您的应用是原生应用还是将 HTML 内容加载到 WebView 中?如果我没记错的话,Marshmallow 之前有一个缺陷,任何使用 WebView 的 Activity 都无法正确收集垃圾。
-
不,不是原生应用 (JNI) 且不使用 WebView
标签: android android-intent memory-leaks