设置:
我有这个应用程序,它在线性路径中有4个活动,非常简单的导航: A - > B - > C - > D
所有活动共享相同的背景图像,并且都有一些常规按钮,textview或edittext。所有这些都在单独的视图中定义xml文件。
背景是渐变,有点沉重。大约3兆作为未压缩的位图。
该应用程序尚未执行任何操作,其唯一的逻辑是启动活动并按下按钮点击它们
我尝试使用MAT来查找内存泄漏但找不到任何内容。我的应用程序中保留的最大大小为656(ko?),应用程序的总保留大小为1520(ko?),我找不到任何可复制的对象。 顺便说一下,dumpsys显示27300(ko?)已分配
问题:
问题:
更新:我想真正的问题是为什么我有一个巨大的内存泄漏(一次5兆),冻结时应用程序大小为27megs,我在MAT中看不到它?
线索信息
在同一时间我有: dumpsys meminfo:
Applications Memory Usage (kB):
Uptime: 74006853 Realtime: 110962243
** MEMINFO in pid 22683 [com.kayenko.sosadresse] **
native dalvik other total
size: 20820 5767 N/A 26587
allocated: 18751 2901 N/A 21652
free: 312 2866 N/A 3178
(Pss): 1357 201 16782 18340
(shared dirty): 2264 1804 5456 9524
(priv dirty): 1280 116 16032 17428
Objects
Views: 0 ViewRoots: 0
AppContexts: 0 Activities: 0
Assets: 2 AssetManagers: 2
Local Binders: 18 Proxy Binders: 16
Death Recipients: 1
OpenSSL Sockets: 0
SQL
heap: 0 MEMORY_USED: 0
PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0
这个统治者树:
任何人都知道我想要寻找的东西。
答案 0 :(得分:7)
在Android中,内存是一个非常棘手的主题。
每个应用都会根据设备获得堆内存限制。此堆内存是dalvik内存加本机内存,您可以将其视为dumpsys meminfo
结果中的总列。 dalvik内存处理除了位图之外的所有内容,这些内容在本机内存中分配(在Honeycomb之前的Android版本中也是如此)。
说过我只能回答你的一些问题:
据我所知,Android将始终为Bitmaps分配内存,即使它们是相同的。因此,在您的情况下,每个活动都会为您的背景分配内存。
我不知道使用主题是否更好,你必须尝试。
一方面,当设备有足够的内存来处理下一个活动时,不会回收活动。当您按下后退按钮时,每个活动都被推到一堆。如果Android需要更多内存,它会从堆中删除一个活动来释放其内存(回到第一个问题,也许这就是不共享内存的原因)。另一方面,您可以设置活动launchMode
来更改此行为(看看here)。
我认为MAT不显示本机内存数据。使用dumpsys meminfo
的原生列查看您为位图分配的内存量。
我自己很难处理OutOfMemory问题。现在我有一个更明确的想法 它是如何工作的,我能够使用大文件而不会耗尽内存。我强烈推荐这两个对我有帮助的资源:
祝你好运!答案 1 :(得分:4)
因此经过数小时的调查和Xavi的帮助后,结果如下:
问。为什么Android会在同一背景下多次解压缩,每次活动一次?似乎效率低下。
一个。尽管通过某种方式让位图在各个活动之间共享似乎是合乎逻辑的,因为我们处于内存很少的移动设备上,但这似乎并不存在于Android中。每次在不同的活动中使用位图时,它都会被解压缩到本机内存。
问。是否有可能通过使用主题来克服这个问题,或者我会看到相同的“按活动分配一个位图”的怪异?
在实验之后,使用主题消耗的内存与在布局的xml中明确设置位图所使用的内存量完全不同。这对我来说很奇怪,因为样式是关于将属性分组到同一个地方。
问。为什么关闭后不收回活动?
一个。嗯,我不确定,但我发现,这几乎只有在调试时才会给我OOM错误。从设备启动应用程序时,几乎从未发生过。调试过程中出现故障?在你完成5个小时测试之前尝试一下。
问。为什么MAT和dumpsys呈现不同的数字?
一个。 Xavi的答案是正确的,dumpsys meminfo显示分配的所有内存(native + dalvik),而MAT只显示Dalvik。由于位图像素在本机存储器中分配,因此MAT不会看到它。这在Android 3.0之前才有效,他们改变了分配方案并使位图的像素数据适合Dalvik。
问。我是如何解决我的问题的
一个。首先,这可能不是一个问题,不调试。其次,为了安全起见,我用一个带有径向渐变的形状替换了渐变png并使用了
getWindow().setFormat(PixelFormat.RGBA_8888);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER);
在我的活动中创建以避免绑扎。我仍然会在一些设备上使用条带,但我宁愿使用条带而不是FC
答案 2 :(得分:0)
当您销毁活动时,您需要显式回收用作背景的位图。代码将是这样的:
@Override
protected void onDestroy () {
Drawable drawable = getView().getBackground();
if (drawable instanceof BitmapDrawable) {
((BitmapDrawable)drawable).getBitmap().recycle();
}
drawable.setCallback(null);
getView().setBackgroundDrawable(null);
super.onDestroy();
}
也许您需要为嵌套视图递归释放资源,但这取决于您的布局结构。这是一般情况