Android:位图回收()如何工作?

发布于 2024-09-25 14:14:40 字数 349 浏览 3 评论 0原文

假设我已经在位图对象中加载了图像,例如

Bitmap myBitmap = BitmapFactory.decodeFile(myFile);

现在,如果我加载另一个位图(例如

myBitmap = BitmapFactory.decodeFile(myFile2);

第一个 myBitmap 会发生什么?)会发生什么?它是否被垃圾收集,或者我是否必须在加载另一个位图之前手动对其进行垃圾收集,例如。 myBitmap.recycle()

另外,有没有更好的方法来加载大图像并在途中回收时依次显示它们?

Let's say I have loaded an image in a bitmap object like

Bitmap myBitmap = BitmapFactory.decodeFile(myFile);

Now, what will happen if I load another bitmap like

myBitmap = BitmapFactory.decodeFile(myFile2);

What happens to the first myBitmap? Does it get Garbage Collected or do I have to manually garbage collect it before loading another bitmap, eg. myBitmap.recycle()?

Also, is there a better way to load large images and display them one after another while recycling on the way?

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

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

发布评论

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

评论(5

帅气称霸 2024-10-02 14:14:40

当您解码第二个位图时,第一个位图不是垃圾收集垃圾收集器将在稍后决定时执行此操作。如果您想尽快释放内存,您应该在解码第二个位图之前调用recycle()

如果你想加载非常大的图像,你应该重新采样它。这是一个示例:将图像加载到位图时出现奇怪的内存不足问题对象

The first bitmap is not garbage collected when you decode the second one. Garbage Collector will do it later whenever it decides. If you want to free memory ASAP you should call recycle() just before decoding the second bitmap.

If you want to load really big image you should resample it. Here's an example: Strange out of memory issue while loading an image to a Bitmap object.

ぃ双果 2024-10-02 14:14:40

我认为问题是这样的:在 Android 之前的 Honeycomb 版本上,实际的原始位图数据并不存储在虚拟机内存中,而是存储在本机内存中。当相应的 java Bitmap 对象被 GC 时,该本机内存将被释放。

但是,当你用完本机内存时,dalvik GC不会被触发,因此你的应用程序可能使用很少的java内存,因此dalvik GC永远不会被调用,但它位图使用大量本机内存,最终导致 OOM 错误。

至少这是我的猜测。值得庆幸的是,在 Honeycomb 及更高版本中,所有位图数据都存储在 VM 中,因此您根本不必使用 recycle()。但对于数以百万计的 2.3 用户(碎片握拳),您应该尽可能使用 recycle() (这是一个巨大的麻烦)。或者您也可以调用 GC。

I think the problem is this: On pre-Honeycomb versions of Android, the actual raw bitmap data is not stored in VM memory but in native memory instead. This native memory is freed when the corresponding java Bitmap object is GC'd.

However, when you run out of native memory, the dalvik GC isn't triggered, so it is possible that your app uses very little of the java memory, so the dalvik GC is never invoked, yet it uses tons of native memory for bitmaps which eventually causes an OOM error.

At least that's my guess. Thankfully in Honeycomb and later, all bitmap data is stored in the VM so you shouldn't have to use recycle() at all. But for the millions of 2.3 users (fragmentation shakes fist), you should use recycle() wherever possible (a massive hassle). Or alternatively you may be able to invoke the GC instead.

温暖的光 2024-10-02 14:14:40

在加载下一张图像之前,您需要调用 myBitmap.recycle()。

根据 myFile 的来源(例如,如果您无法控制原始大小),在加载图像时,您应该将图像缩放到显示大小,而不是简单地重新采样一些任意数字。

if (myBitmap != null) {
    myBitmap.recycle();
    myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
    original.recycle();
original = null;

我缓存了displayWidth &我在活动开始时初始化的静态中的 displayHeight 。

Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();

You will need to call myBitmap.recycle() before loading the next image.

Depending on the source of your myFile (E.g. if it is something you have no control over the original size), when loading an image instead of just simply resampling some arbitrary number, you should scale the image to the display size.

if (myBitmap != null) {
    myBitmap.recycle();
    myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
    original.recycle();
original = null;

I cache the displayWidth & displayHeight in a static that I initialized at the start of my Activity.

Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();
桃扇骨 2024-10-02 14:14:40

一旦位图被加载到内存中,实际上它是由两部分数据组成的。
第一部分包括有关位图的一些信息,另一部分包括有关位图像素的信息(它由字节数组组成)。
第一部分存在于Java使用的内存中,第二部分存在于C++使用的内存中。可以直接使用对方的内存。
Bitmap.recycle()用于释放C++的内存。
如果你只这样做,GC将收集java的部分,而C的内存总是被使用。

Once bitmap had been loaded in memory , in fact it was made by two part data.
First part include some information about bitmap , another part include information about pixels of bitmap( it is maked up by byte array).
First part exisits in Java used memory, second part exisits in C++ used memory. It can use each other's memory directly.
Bitmap.recycle() is used to free the memory of C++.
If you only do that,the GC will collection the part of java and the memory of C is always used.

咽泪装欢 2024-10-02 14:14:40

蒂姆姆是对的。

根据 :
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html< /a>

此外,在 Android 3.0(API 级别 11)之前,位图的后备数据存储在本机内存中,而该内存不会以可预测的方式释放,可能会导致应用程序短暂超出其内存限制,并且崩溃。

Timmmm was right.

according to :
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

In addition, prior to Android 3.0 (API Level 11), the backing data of a bitmap was stored in native memory which is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash.

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