Android中位图的OutOfMemoryError

Android中位图的OutOfMemoryError,android,bitmap,Android,Bitmap,我正在开发一个演示应用程序,其中我正在播放很多图像(位图)。我使用全局位图对象在多个活动中显示同一图像。但是,当我尝试使用Bitmap.createBitmap(…)创建位图时,使用它,我将获得OutOfMemoryError。我尝试过使用,但仍然遇到同样的错误,它正在使我的应用程序崩溃,并通过OutOfMemoryError 我被困在这个问题上了。任何人都有办法避免这种情况吗 提前谢谢 剪切图像后,我得到位图,因此我使用以下代码解码位图大小。 public static Bitmap load

我正在开发一个演示应用程序,其中我正在播放很多图像(位图)。我使用全局位图对象在多个活动中显示同一图像。但是,当我尝试使用Bitmap.createBitmap(…)创建位图时,使用它,我将获得OutOfMemoryError。我尝试过使用,但仍然遇到同样的错误,它正在使我的应用程序崩溃,并通过OutOfMemoryError

我被困在这个问题上了。任何人都有办法避免这种情况吗

提前谢谢

剪切图像后,我得到位图,因此我使用以下代码解码位图大小。

public static Bitmap loadFromBitmap( Context context, Bitmap b, int maxW, int maxH ) throws IOException {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        Bitmap bitmap = null;
        options.inScaled = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        options.inJustDecodeBounds = true;
        BufferedInputStream stream = null;
        ByteArrayOutputStream outstream = new ByteArrayOutputStream();
        b.compress(CompressFormat.JPEG, 100, outstream);
        InputStream is = new java.io.ByteArrayInputStream(outstream.toByteArray());

        stream = new BufferedInputStream(is, 16384 );
        if ( stream != null ) {
            options.inSampleSize = calculateInSampleSize( options, maxW, maxH );
            stream = null;
            stream = new BufferedInputStream(is, 16384 );
        } else {
            return null;
        }
        options.inDither = false;
        options.inJustDecodeBounds = false;
        options.inPurgeable = true;
        bitmap = BitmapFactory.decodeStream( stream, null, options );
        if ( bitmap != null ) bitmap = BitmapUtils.resizeBitmap( bitmap, maxW, maxH );
        return bitmap;
    }

    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and width
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

使用选项编辑代码。inpurgable=true和op.inInputShareable=true
并在代码中使用一些节省内存的方法

在每次调用
loadFromBitmap()
之前,尝试添加
System.gc()

啊-谷歌在安卓系统中实现位图处理可能会有很多精彩的战斗

每当我有了内存,我就会倾向于做一些内存分析——很多时候(虽然不总是),这是因为一个人做了一些错误的事情(例如,出乎意料的内存密集型)。在浏览代码时,我有点困惑,需要强制代码通过三个流,最终得到一个位图。我觉得好像我遗漏了一些信息来理解这一点,但如果我是你,我肯定会看看你在这些步骤中分配了多少内存(heap dump->hprof conv->memory analyzer是你的朋友)

然而,我怀疑你可能正在寻找的是。事实上,我自己最近才发现这一点,但我认为它几乎完全符合您的要求-允许您从位图(inputstream)解码一个区域,而无需将整个位图加载到内存中(您还可以获得宽度/高度)。唯一的缺点是它只支持安卓2.3.3+,但现在市场占有率超过90%,所以这应该不是一个大问题。我已经用这个做了一些非常巧妙的工作(6000x4000图像的平滑平移和缩放)-如果使用正确,它肯定是有效的内存

[编辑]

我最近使用BitMapRegionCoder开发了自己的dumb实现,它可以处理非常大的位图的平移、翻转和收缩缩放。您可以在以下位置找到代码(ASL2.0)


您要查看的类是BitmapSurfaceRenderer。到目前为止,我已经用高达8000x4000的图像对它进行了测试,它似乎工作得很好。当我有时间时,我会推出一个简单的示例应用程序,演示如何使用它。

尝试在解码之前消除
扩展
,例如清空指针(由于流的类型,关闭此特定流不会起任何作用)

你在这里做了一个相当广泛的手术,所以我们需要尽可能轻

您的代码还缺少使用close()关闭输入流(这不是这里的错误,但仍然应该在解码流之后完成)


试着看看Nostras,因为它可以有效地将图像加载到特定大小的容器中,即在您需要处理它们之前调整大小并压缩它们。它还支持内容URI,这将一次为您提供帮助

在清空位图对象之前,使用方法
Bitmap.recycle()

以下是示例:

 public final void setBitmap(Bitmap bitmap) {
   if (this.myBitmapImage != null) {
      this.myBitmapImage.recycle();
   }
    this.myBitmapImage = bitmap;
 }
接下来,您可以更改
myBitmapImage
,而无需调用
System.gc()
,如下所示:

 setMyBitmap(anotherBitmap);
   setMyBitmap(null);

这将有助于youThanks Ram,但我在问题中提到了相同的链接:(@anddev你最终会增加图像吗?你从哪里获得图像?我从画廊和相机获得图像。在我裁剪这些图像之后。在整个过程中,我的应用程序崩溃了,因为位图的大小增加了。那么我该如何处理呢?我不知道(发布您的代码和logcat…使用system.gc()清除垃圾值;加载imageMemory saving方法时使用了什么?我指的是哪种类型的方法?您能举个例子吗?我已经使用了“options.inpurgable=true”在我的代码中。还有其他地方需要它吗?也可以使用options.inInputShareable=true。尝试使用这两个选项来更新此视频()看起来很棒。你有没有找到时间来发布一个简单的示例应用程序?我还没有时间真正做任何正确的事情来演示如何让一切正常工作(特别是使用片段,这是我在自己的项目中使用的),但有一个非常非常简单的示例应用程序,使用BitmapSurfaceRenderer,这正是我想要的。谢谢。
 setMyBitmap(anotherBitmap);
   setMyBitmap(null);