回收Bitmap,还是不回收Bitmap?

10

几天前,我们在Play商店发布了一款涉及高质量位图编辑的应用程序。

一切都进行得很顺利,直到我们意识到有20%的设备会出现内存不足的错误。因此,我们检查了代码并发现Android在某些设备上没有释放用于存储位图数据的本机内存。在这种情况下,我们欢迎回收命令。

内存错误消失了(至少在hd设备中是这样)。总之,我们很高兴。但是今天我们开始看到50%的设备开始出现另一个错误:“无法复制已回收的位图”。

我们很失望。在我们的代码中,有两个bitmap.copy()行,在其中一半的设备上不能同步执行这两行:

Bitmap anotherBitmap = bitmap.copy( bitmap.getConfig(), true );
bitmap.recycle();

所以我们去掉了回收站并发布了另一个更新,决定限制设备屏幕尺寸,这样小尺寸的设备就不会给我们带来差评。

我有一个问题。为什么有些设备可以在回收之前复制,而另一半则不能?

我阅读了谷歌的位图相关文档,并已经知道位图是如何存储在虚拟机堆和本地堆上的,内存溢出错误时垃圾回收是如何工作的等等。谷歌提供的用于加载和编辑大型位图的示例代码与我们的几乎相同。

阅读了许多博客、谷歌组线程、github代码示例...我觉得我仍需要一份关于Android位图的好文档/书籍。

PS:我们已经在解码时使用inSampleSize来缩放位图。

编辑--以下是一些崩溃报告中的数据:

所有设备都没有root权限。在大多数情况下,使用的内存介于25%到35%之间。

Manufacturers: 
57% LG
31% Samsung
10% Casper Via V5 (Turkey based company, sells rebranded Chinese phones)

Devices:
81% LG D855 (G3)
18% LG D802TR (G2)
----
66% Samsung SM N910C (Galaxy Note 4)
20% Samsung SM A700F (Galaxy A7)

Operating Systems:
68% Android 5
31% Android 4

OS 5 Details
69% Android 5.0
30% Android 5.0.1

OS4 Details
66% Android 4.4.2
33% Android 4.4.4

据我所知,如果位图被放置在本地内存中,这与您运行的Android版本有关。较新版本的Android不会将它们存储在本地RAM中,在这些版本上,您不需要调用recycle。当您调用copy和recycle时,实际发生的情况取决于OEM制造商和Android版本,您能否提供有关设备和平台的更多信息? - JohanShogun
一个可能的做法是仅在运行着姜饼或更早版本的手机上调用回收操作(如果你所拥有的关于哪些手机会出现内存问题的数据支持这个想法)。 - JohanShogun
关于位图的文档,最快最简单的方法是查看AOSP(Android Open Source Project)是如何处理的。一些厂商会进行更改(三星是最大的罪犯),但它应该足以为您提供有关大多数设备如何处理这些事情的足够信息。 AOSP可以轻松搜索:http://androidxref.com - JohanShogun
@JohanShogun 刚刚添加了崩溃报告的详细信息以进行检查。但据我所见,数据没有特定的设备或操作系统版本。一些带有操作系统5的LG手机崩溃了,一些带有操作系统4的LG手机也崩溃了,但有些则没有。三星设备也是如此。我们支持的最低版本为Jelly Bean(4.1),因此不支持Gingerbread。 - emrahgunduz
1个回答

0

你确定有某些原因吗?

bitmap.copy(..)

不会被调用两次吗?

i.e.:

//第一次调用 Bitmap anotherBitmap = bitmap.copy(bitmap.getConfig(), true); bitmap.recycle();

[...]

//第二次调用 Bitmap anotherBitmap = bitmap.copy(bitmap.getConfig(), true); bitmap.recycle();


1
是的, recycle 只使用一次。我们使用这个第一个副本为效果。第二个副本用于重置编辑过的图像,该图像是从第一个副本创建的,而非原始的。具有空指针异常的设备告诉我们同一类的同一行出现了问题。只有约 50% 的设备会崩溃。其余没有 recycle 的设备没有问题。目前,我们改变了我们的编辑流程并完全删除了 recycle。很可能我们将把图像读取移到 NDK 中以实现更好的内存管理,因为当涉及到位图时,Android 的 GB 是一团糟。 - emrahgunduz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接