【问题标题】:OutOfMemory Exception when decoding bitmap [duplicate]解码位图时出现OutOfMemory异常[重复]
【发布时间】:2014-08-06 16:59:07
【问题描述】:

我的应用使用来自网络的图像来设置壁纸。但是,当我尝试使用 BitmapFactory 使用 decodeStream 时,一些使用速度较慢的手机的用户会收到 OutOfMemory 异常。此图像永远不会显示在应用程序上,它只是加载,然后设置为壁纸。我在网上搜索过,但找不到任何有助于解决问题的资源。

代码:

公共无效 setWallpaperMethod() {

    InputStream in = null;
    try {
        in = new java.net.URL(urldisplay).openStream();
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    final Bitmap bitmap = BitmapFactory.decodeStream(in);
    myWallpaperManager = WallpaperManager
            .getInstance(getApplicationContext());

    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                myWallpaperManager.setBitmap(bitmap);
                Toast.makeText(MainActivity.this,
                        "Teamwork! Wallpaper set.", Toast.LENGTH_LONG)
                        .show();
            } catch (IOException e) {
                Toast.makeText(
                        MainActivity.this,
                        "Damnit, clickers! Wallpaper wasn't set. Try killing and restarting the app?",
                        Toast.LENGTH_LONG).show();
            }
        }

    });

}

变量urldisplay是一个字符串,等于一个URL(例如,一个imgur图像)。此外,该方法在线程中运行,因此不存在 UI 线程锁定的风险。

那么有人知道如何解决这个 OutOfMemory 异常吗?感谢所有帮助。

【问题讨论】:

  • 那是因为图像对于设备来说很大。检查图像是否不大于 1024。
  • 为什么不用public void setStream (InputStream data) 而不是setBitmap
  • njzk2:我自己编写了代码,将几个不同来源的代码拼接在一起,所以它可能并不完美:P
  • 鉴于问题是关于壁纸管理器的,并且重复问题中给出的答案 a/ 与接受的答案不同,并且 b/ 在这种情况下不相关,并且考虑到接受的答案此问题不适用于重复问题,我投票支持重新提出问题。

标签: java android out-of-memory


【解决方案1】:

目前,您正在打开一个输入流,读取它,解码一个完整的位图,然后将其传递给管理器,管理器会将其转换为 png 并存储以供以后使用。

相反,您可以打开输入流,将其传递给管理器,该管理器现在负责简单地存储它以供以后使用。

如您所见,这是一种解码和一种编码。

然后,壁纸管理器将负责显示图像,并相应地处理图像大小。

myWallpaperManager = WallpaperManager
        .getInstance(getApplicationContext());
myWallpaperManager.setStream(in);

瞧!

(假设壁纸管理器正确处理过大的图像,但很可能是这种情况)

【讨论】:

  • 非常感谢,伙计!只需将它放在我的应用程序中,它就可以在我的手机上正常运行 :) 那么,它现在可以在速度较慢的手机上运行而不会抛出 OutOfMemoryException 吗? (即三星展览)
  • 应该,是的。壁纸应用应处理图像并在需要时进行必要的重新采样。
【解决方案2】:

看看这个链接..

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

Android 文档建议您对图像进行下采样。使用此方法计算样本大小:

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;
}

那么你会做这样的事情:

// First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多