【问题标题】:Android BitmapFactory.decodeFile slows down until out of memoryAndroid BitmapFactory.decodeFile 变慢直到内存不足
【发布时间】:2014-06-22 20:10:50
【问题描述】:

我正在处理多达 1200 张图像。在此处找到的先前问题的帮助下,我将其优化为从 100 个图像到 500 个图像。现在,这就是我所拥有的:

   public Bitmap getBitmap(String filepath) {
        boolean done = false;
        int downsampleBy = 2;
        Bitmap bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filepath, options);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Config.RGB_565;
        while (!done) {
            options.inSampleSize = downsampleBy++;
            try {
                bitmap = BitmapFactory.decodeFile(filepath, options);
                done = true;
            } catch (OutOfMemoryError e) {
                // Ignore.  Try again.
            }
        }
        return bitmap;
    }

这个函数在循环中被调用,它运行得非常快,直到它到达第 500 张图像。此时它会变慢,直到它最终在第 600 张图像左右停止工作。

此时我不知道如何对其进行优化以使其正常工作。您认为发生了什么,我该如何解决?

编辑

            // Decode BItmap considering memory limitations
    public Bitmap getBitmap(String filepath) {
        Bitmap bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filepath, options);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Config.RGB_565;
        options.inDither = true;
        options.inSampleSize= calculateInSampleSize(options, 160, 120);

        return bitmap = BitmapFactory.decodeFile(filepath, options);
    }

    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) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

对已接受的答案进行了更改。使用 Google 教程中的函数来获得正确的样本量。在清单中添加了 largeHeap,并且在循环所有图像之前只调用一次 System.gc()。

【问题讨论】:

  • 我不知道这是不是一个糟糕的计划,但是您是否尝试过调用 System.gc() 来防止内存耗尽?
  • @Zhuinden 我没有,我应该在哪里调用这个?

标签: android bitmapfactory


【解决方案1】:

首先,您永远不要期望捕获错误。此处描述:Java documentation 错误是 Throwable 的子类,表示合理的应用程序不应尝试捕获的严重问题。

关于加载位图有一些帮助:Android Developers | Loading large bitmaps

您可以通过在应用程序清单中声明 largeHeap="true" 属性来获得更多内存。

还有System.gc() 调用可能有助于释放一些未使用的内存,但我不会真正依赖该调用。

【讨论】:

  • 我是在 StackOverflow 的答案中找到它之后才这样做的。我确实觉得这不是正确的方法,但它比这个问题的 caculateInSampleSize 函数效果更好:stackoverflow.com/questions/21392972/… 我将尝试更改 largeHeap 属性和 System.gc() 调用,看看它是否有帮助@Sipka
  • 通过添加 largeHeap 并调用 System.gc() 我让它处理 1200 个图像中的 788 个图像。所以它确实有帮助,但是它在 788 个时崩溃
  • 您可以尝试在每次尝试加载图像之前调用System.gc()。垃圾收集器将尝试释放尽可能多的内存,包括之前被回收的位图。
  • 谢谢,这就是我现在正在做的事情。在我的 Nexus 5 上对其进行了测试,所有图像都已处理,但是该应用程序将用于的设备尚未工作。我不知道这是否只是硬件限制,还有其他方法可以释放更多内存吗?
  • 感谢您的帮助。由于该设备不是很强大,我决定降低图像质量并且它工作正常。恐怕这不是最终的解决方案,因为我相信使用更多图像将无法正常工作。我接受你的回答,因为它正在做我现在需要的!再次感谢
猜你喜欢
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多