Art*_*kii 87 lifecycle android out-of-memory android-activity
我花了整整4天时间尽我所能来弄清楚我正在开发的应用程序中的内存泄漏,但事情很久以前就停止了.
我正在开发的应用程序具有社交性,因此请考虑配置文件活动(P)并列出包含数据的活动 - 例如徽章(B).您可以从配置文件跳转到徽章列表,转到其他配置文件,其他列表等.
所以想象一下这样的流程P1 - > B1 - > P2 - > B2 - > P3 - > B3等.为了保持一致性,我正在加载同一个用户的配置文件和徽章,所以每个P页面是相同的,所以是每个B页面.
这个问题的一般要点是:在导航了一下之后,根据每个页面的大小,我在随机位置得到了一个内存不足的例外 - 位图,字符串等 - 它似乎并不一致.
在做了一切可以想象的事情来弄清楚为什么我的内存不足之后,我什么也没想出来.我不明白的是,如果Android在加载时耗尽内存而不是崩溃,那么为什么Android不会杀死P1,B1等.如果我通过onCreate()和onRestoreInstanceState()返回它们,我会期望这些早期活动会死亡并复活.
更别说这个 - 即使我做P1 - > B1 - >返回 - > B1 - >返回 - > B1,我仍然会崩溃.这表明某种内存泄漏,即使在转储hprof并使用MAT和JProfiler后,我也无法查明它.
我已禁用从Web加载图像(并增加了加载的测试数据以弥补它并使测试公平)并确保图像缓存使用SoftReferences.Android实际上试图释放它所拥有的一些SoftReferences,但就在它崩溃内存之前.
徽章页面从Web获取数据,从BaseAdapter将其加载到EntityData数组中并将其提供给ListView(我实际上使用的是CommonsWare的优秀MergeAdapter,但在此Badge活动中,实际上只有1个适配器,但我无论哪种方式都想提到这个事实).
我已经完成了代码并且无法找到任何可能泄漏的内容.我清除并取消了我能找到的所有内容,甚至是System.gc()左右,但应用程序崩溃了.
我仍然不明白为什么堆栈上的非活动活动不会被收获,我真的很想知道这一点.
在这一点上,我正在寻找任何提示,建议,解决方案......任何有用的东西.
谢谢.
hac*_*bod 106
我仍然不明白为什么堆栈上的非活动活动不会被收获,我真的很想知道这一点.
这不是事情的运作方式.影响活动生命周期的唯一内存管理是所有进程的全局内存,因为Android决定它在内存上运行不足,因此需要杀死后台进程才能获得回复.
如果你的应用正坐在前台开始越来越多的活动,这是从来没有进入的背景,因此会一直打到其本地进程内存限制的系统以往任何时候都接近杀死它的进程.(当它确实杀死它的进程时,它会杀死托管所有活动的进程,包括当前在前台的任何活动.)
所以我觉得你的基本问题是:你让太多的活动同时运行,和/或每个活动都持有太多的资源.
您只需重新设计导航,而不是依赖于堆叠任意数量的潜在重量级活动.除非你在onStop()中做了大量的事情(比如调用setContentView()来清除活动的视图层次结构并清除它可能持有的其他任何变量),你只会耗尽内存.
您可能需要考虑使用新的Fragment API将这个任意堆栈的活动替换为更紧密地管理其内存的单个活动.例如,如果使用片段的后向堆栈功能,当片段进入后台堆栈并且不再可见时,将调用其onDestroyView()方法以完全删除其视图层次结构,从而大大减少其占用空间.
现在,只要你在你按下背面的流崩溃,去一个活动,请按返回,去到另一个活动等,并永远不会有一个深筹码,然后是你只是有一个泄漏.这篇博客文章描述了如何调试泄漏:http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html
vov*_*kab 21
一些技巧:
确保您不是泄漏活动背景.
确保不要保留对位图的引用.在Activity#onStop中清理所有的ImageView,如下所示:
Drawable d = imageView.getDrawable();
if (d != null) d.setCallback(null);
imageView.setImageDrawable(null);
imageView.setBackgroundDrawable(null);
Run Code Online (Sandbox Code Playgroud)如果您不再需要它们,请回收位图.
如果你使用内存缓存,比如memory-lru,请确保它没有使用很多内存.
不仅图像占用大量内存,请确保不要在内存中保留太多其他数据.如果您的应用中有无限列表,则很容易发生这种情况.尝试在DataBase中缓存数据.
在android 4.2上,有一个带有硬件加速的bug(stackoverflow#13754876),所以如果你hardwareAccelerated=true
在你的清单中使用它会泄漏内存.GLES20DisplayList
- 继续保持引用,即使你执行了步骤(2)并且没有其他人引用此位图.在这里你需要:
a)禁用api 16/17的硬件加速;
或
b)分离持有位图的视图
对于Android 3+,您可以尝试android:largeHeap="true"
在您的AndroidManifest
.但它不会解决你的记忆问题,只是推迟它们.
如果您需要,如无限导航,那么片段 - 应该是您的选择.所以你将有1个活动,它只会在片段之间切换.这样你也可以解决一些内存问题,比如4号.
使用Memory Analyzer查找内存泄漏的原因.
以下是来自Google I/O 2011的非常好的视频:Android应用程序的内存管理
如果您处理位图,则必须阅读:有效显示位图
在我的案例中,真正帮助解决内存问题的事情之一最终是将我的位图的 inPurgeable 设置为 true。请参阅为什么我不使用 BitmapFactory 的 inPurgeable 选项?以及答案的讨论以获取更多信息。
Dianne Hackborn 的回答和我们随后的讨论(也感谢 CommonsWare)帮助澄清了我感到困惑的某些事情,所以谢谢你。
归档时间: |
|
查看次数: |
37445 次 |
最近记录: |