【问题标题】:OutOfMemoryError when Loading Bitmaps加载位图时出现 OutOfMemoryError
【发布时间】:2014-08-13 16:11:58
【问题描述】:

我正在创建的应用程序需要从我们的服务器中提取一些图像,并显示在一个页面上。用户可以进入几个不同的类别,每个类别都有自己的图像。问题是在连续进入 2-3 个类别(取决于这些类别中有多少图像)后,应用程序没有更多内存,并且无法在不崩溃的情况下显示位图。

我希望能够在每次用户进入新类别时清除内存,以便旧类别的图像不再存储在内存中,从而为相关类别的图像腾出空间。我不确定这是否是一个好方法,或者如果是的话,我什至不确定如何去做。

如果有人有更好的解决方案,请告诉我。一个想法是一次只加载大约 20 张图片,并等到用户滚动到底部再加载更多图片,但是由于我们的客户付费将他们的图片放在应用程序上,这将导致某些图片的流量减少,所以这不是理想的解决方案。不过也不是没办法。

这是我用来加载图像的代码: 编辑:我的错误我发布了错误的代码,这是我正在使用的真实代码:

@SuppressWarnings("deprecation")
public Drawable loadImageFromWebOperations(String url, String imagePath) {
    try {
        if(Global.couponBitmaps.get(imagePath) != null){
            scaledHeight = Global.couponBitmaps.get(imagePath).getHeight();
            return new BitmapDrawable(getResources(), Global.couponBitmaps.get(imagePath));
        }
        Drawable d = null;
        File f = new File(getBaseContext().getFilesDir().getPath().toString() + "/" + imagePath + ".png");
        if (f.exists()) {
            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            int scaledWidth = 0;
            try {
                display.getSize(size);
                scaledWidth = size.x;
            } catch (java.lang.NoSuchMethodError ignore) {
                scaledWidth = display.getWidth();
            }
            Bitmap bitmap = null;

            BitmapScaler scaler = new BitmapScaler(f, scaledWidth);
            bitmap = scaler.getScaled();

            scaledHeight = bitmap.getHeight();

            d = new BitmapDrawable(getResources(), bitmap);
            Global.couponBitmaps.put(imagePath, bitmap);
        } else {
            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            int scaledWidth = 0;
            try {
                display.getSize(size);
                scaledWidth = size.x;
            } catch (java.lang.NoSuchMethodError ignore) {
                scaledWidth = display.getWidth();
            }
            Bitmap bitmap = BitmapFactory.decodeStream((InputStream) new URL(url).getContent());
            int height = bitmap.getHeight();
            int width = bitmap.getWidth();
            scaledHeight =  (int) (((scaledWidth * 1.0) / width) * height);
            f.getParentFile().mkdirs();
            f.createNewFile();
            OutputStream output = new FileOutputStream(f);
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, output);
            output.close();
            bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, false);
            d = new BitmapDrawable(getResources(), bitmap);
            Global.couponBitmaps.put(imagePath, bitmap);
        }
        return d;
    } catch (MalformedURLException e) {
        e.printStackTrace();
        return null;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    } catch (OutOfMemoryError e){
        e.printStackTrace();
        return null;
    }
}

如果有人知道是否有更有效的加载图像的方法,或者是否有在绘制之前清除内存的方法,将不胜感激,谢谢。

【问题讨论】:

标签: android image bitmap out-of-memory


【解决方案1】:

每次创建新的 Drawable 和 BitmapDrawable 时,使用一个 Drawable 并在其上刷新图像。

【讨论】:

    【解决方案2】:

    android 中的位图有点棘手。我的第一个应用程序需要在 gridview 中使用大量图像 - 我也遇到了很多 OOM 问题。

    我最终使用了 nostra13 的“Universal Image Loader”,因为它似乎是满足我需要的最佳解决方案。它有很多内置功能,如磁盘缓存、内存缓存、位图大小、线程池大小、图像缩放等。也有工作示例。 :)

    Nostra13 Universal Image Loader

    有几点要记住:

    • 回收您的位图,然后再显示下一个,否则他们将 堆积在内存中,你会得到OOM
    • 如果使用通用图像加载器,请确保使用 .bitmapConfig(Bitmap.Config.RGB_565),因为它使用每个图像的内存最少。
    • 如果您计划在网格视图或列表视图中显示大量图像,我使用的方法是从您的 API 加载两个不同的图像,一个非常小(100x100 ish)用于缩略图视图,另一个是完整的大小图像。这样您在显示缩略图时就不会耗尽内存。然后只有当用户点击缩略图时,才会加载该位置的全尺寸图片。

    希望这会有所帮助。 :)

    【讨论】:

      【解决方案3】:

      由于您是从服务器加载Bitmaps,您可能应该使用图像加载库

      强大的库例如:

      它们允许您使用Bitmap 和在加载过程中做任何事情。还支持Chaching。

      在我看来,UniversalImageLoader 稍微强大一些,Picasso 更易于使用。

      【讨论】:

      • 我刚刚意识到我发布了错误的代码,我编辑了我的原始评论以反映这一点,但 Drawable 不在资源文件夹中,它们存储在服务器上。我不确定您的解决方案是否仍然适用。
      • 不,在这种情况下它不适用。您可能应该继续使用图像加载库。最强大的可能是通用图像加载器和毕加索。我更新了我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 2014-09-07
      • 1970-01-01
      相关资源
      最近更新 更多