与 Bitmap 不同,byte[] 是否会被垃圾回收?或者说是一样的吗?

发布于 2024-12-29 03:53:09 字数 307 浏览 2 评论 0 原文

我的 Android 应用程序中遇到了一堆奇怪的(而且很难发现)内存泄漏。我没有任何静态位图(这是所有有关泄漏位图的教程告诉您不要做的事情)。不过,我确实有一个位图存储在我的应用程序类中,我的许多活动正在使用该位图。当最后一个活动退出时,我正在调用 recycle() ,但我想知道将数据存储为 byte[] 并创建是否会更安全在每个使用它的 Activity 中本地生成一个 Bitamp,然后在完成后立即释放它。我很好奇 byte[] 的构造是 VM 比 Bitmap 更容易进行垃圾收集(它似乎完全糟糕)。

非常感谢所有帮助。

I'm experiencing a bunch of wacky (and very hard to find) memory leakage in my Android app. I don't have any static Bitmaps (which is what all the tutorials regarding leaking Bitamps tell you not to do). I do however, have a Bitmap that I'm storing in my Application class which is being used by a bunch of my activities. I AM calling recycle() on that when the last activity exits, but I'm wondering if it would be safer to just store the data as a byte[] and create a Bitamp out of it locally in each Activity that uses it, and then release it as soon as it's done. I'm curious of byte[] is construct that the VM has an easier time garbage collecting than the Bitmap (which it seems to totally suck at).

All help GREATLY appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

水染的天色ゝ 2025-01-05 03:53:09

Bitmap 更改为 byte[] 并不能解决问题,这是由维护对 Bitmap 对象的引用引起的。当最后一个 Activity 退出时,您应该将引用设置为 null,而不是调用 recycle()。这将完成调用 recycle() 所做的一切,并允许 GC 获取 Bitmap 对象本身。 (GC 在回收时不区分 Bitmapbyte[]。未引用的对象就是未引用的对象...)

唯一需要建议的其他事项(如果 Bitmap 确实是内存泄漏的根源)是使用 WeakReference 在您的应用程序类中而不是硬引用。然后每个活动都可以get()实际的Bitmap(如果它仍然存在)。那么你不必将其设置为null;当没有硬引用时,GC 将自动收集位图,留下一个空的弱引用。

Changing from a Bitmap to a byte[] isn't going to solve the problem, which is caused by maintaining a reference to the Bitmap object. Instead of calling recycle(), you should set the reference to null when the last activity exits. That will do everything that calling recycle() does plus allows the GC to harvest the Bitmap object itself. (The GC doesn't distinguish between Bitmap and byte[] when it comes to recycling. An unreferenced object is an unreferenced object...)

The only other thing to suggest (if the Bitmap really is the source of your memory leak) is to use a WeakReference<Bitmap> in your application class instead of a hard reference. Then each activity can get() the actual Bitmap (if it's still there). Then you don't have to set it to null; the GC will automatically harvest the Bitmap when there are no hard references, leaving behind an empty weak reference.

情话墙 2025-01-05 03:53:09

如果您正在处理从相机拍摄的位图,您需要非常小心图像的大小。

用相机拍摄的照片可能会很大。当您以位图形式打开图像时,您正在将整个数组加载到内存中。考虑一下配备 5MP 摄像头的 Nexus One。用户使用该设备拍摄的照片最大可达 2048x1536。使用 24 位像素深度,我们谈论的是近 9MB。如果考虑到 16/24 MB 堆限制,这将是巨大

解决方案是使用较小的尺寸,通常您不需要完整尺寸的图像,因为设备的分辨率要低得多,再加上您的 ImageView (或您用来显示的任何其他表面)的尺寸显示位图)通常不会占据整个屏幕。

BitmapFactory.decodeByteArray(...) (和其他工厂方法)可以采用BitmapFactory.Options 对象,其中您可以通过 inSampleSize。这不会影响原始数据,因此您可以保留全尺寸图像并在内存中获取采样位图。您可以将其结合起来,之前使用 inJustDecodeBounds = true 读取图像的大小,然后根据图像的大小和视口的大小计算比例因子,最后获得缩放后的位图。

这个问题可能很方便(不是所选的答案,而是其他两个得分较高的答案): 将图像加载到位图对象时出现奇怪的内存不足问题

编辑:哎呀,发布了错误的问题链接

If you are dealing with bitmaps taken from the camera you need to be very careful with the size of the images.

A picture taken with the camera can be pretty big. When you open the image as a bitmap, you are loading the full array into memory. Consider the Nexus One with a 5MP camera. User pictures taken with the device can be as big as 2048x1536. Using 24 bits pixel depth, we are talking about nearly 9MB. This is huge if take into account the 16/24 MB heap limit.

Solution is to work with a smaller size, usually you won't need the full sized image since the device will have a much lower resolution, plus the size of your ImageView (or any other surface you use to display the bitmap) won't usually take all the screen.

BitmapFactory.decodeByteArray(...) (and other factory methods) can take a BitmapFactory.Options object where you can specify a scale factor through inSampleSize. This doesn't affect the original data, so you can keep your full size image and get a sampled bitmap in memory. You can combine this by previously using inJustDecodeBounds = true to read the size of the image, then calculate the scale factor based on the size of the image and the size of your viewport and finally obtain the scaled bitmap.

This question might be handy (not the chosen answer, but the other two with high score): Strange out of memory issue while loading an image to a Bitmap object

Edit: oops, posted wrong link to question

韬韬不绝 2025-01-05 03:53:09

我知道这个问题已经得到解答,但作为旁注:在处理 Bitamp 时,它是 Android 本地处理的事情之一(即通过 C 代码,而不是 Java 代码)。因此,即使您释放对它的所有引用,它仍然会存储在本机端的内存中并计入您的应用程序。

I know this question has already been answered, but just as a side note: When dealing with Bitamps, it's one of those things that Android handles natively (ie through C code, not Java code). So even if you release all references to it, it'll still be stored in memory on the native side and count against your app.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文