Android:BitmapFactory.decodeStream OutOfMemoryException - SoftReference 是解决方案吗?

发布于 2024-10-14 13:59:46 字数 4508 浏览 6 评论 0原文

我收到 OutOfMemoryException:

E/AndroidRuntime( 3013): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
E/AndroidRuntime( 3013):        at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime( 3013):        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:375)
E/AndroidRuntime( 3013):        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:394)

在以下函数中:

static Bitmap downloadBitmap(String url)
    {
        final HttpClient client = new DefaultHttpClient();
        final HttpGet getRequest = new HttpGet(url);

        try 
        {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();

            // Check HTTP Status code
            if (statusCode != HttpStatus.SC_OK)
            { 
                debugPrint("ImageDownloader StatusCode Error " + statusCode + " while retrieving bitmap from " + url);
                return null;
            }
            else;


            final HttpEntity entity = response.getEntity();

            if (entity != null)
            {
                InputStream inputStream = null;
                try
                {
                    inputStream = entity.getContent(); 
                    if( inputStream == null)
                    {
                        debugPrint("ImageDownloader::downloadBitmap() - INPUTSTREAM = NULL!!!!!!");
                    }
                    else;



                    // THIS LINE IS GIVING THE ERROR
                    final Bitmap bitmap = BitmapFactory.decodeStream( new FlushedInputStream(inputStream));

                    if( bitmap == null)
                    {
                        debugPrint("LocrPhoto::downloadBitmap() - about to return BITMAP =NULL!!!!!!");
                    }
                    else;

                    return bitmap;
                }
                catch (Exception e)
                {
                    // Could provide a more explicit error message for IOException or IllegalStateException
                    getRequest.abort();
                    debugPrint("LocrPhoto::downloadBitmap() Error while decoding bitmap from " + url + "\n"+ e.toString());
                }
                finally
                {
                    if (inputStream != null)
                    {
                        inputStream.close();  
                    }
                    entity.consumeContent();
                }
            }
            else
            {
                debugPrint("LocrPhoto::downloadBitmap("+url+") - entity = NULL!!!!!");
            }
        }
        catch (Exception e)
        {
            // Could provide a more explicit error message for IOException or IllegalStateException
            //getRequest.abort();
            debugPrint("LocrPhoto::downloadBitmap() Error while retrieving bitmap from " + url + "\n"+ e.toString());
        }
        finally
        {
            if (client != null)
            {
                // CLOSE CONNECTION
            }
        }
        debugPrint("LocrPhoto::downloadBitmap("+url+") - returning NULL at end of function");
        return null;
    }

FlushedInputStream (尽管在添加此代码之前我收到了错误):

// A Class to hopefully avoid the BitmapFactory.decodeStream() returning null bug
    //      http://code.google.com/p/android/issues/detail?id=6066
    static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

        @Override
        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L) {
                      int byt = read();
                      if (byt < 0) {
                          break;  // we reached EOF
                      } else {
                          bytesSkipped = 1; // we read one byte
                      }
               }
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }

基本上,我有一个下载图像、将它们放置在框架布局中并淡入和淡出帧以提供幻灯片的活动。框架布局有两个 imageview 子级。

我见过人们谈论 SoftReference 用于防止 OOMExceptions,但我无法理解如何将其应用于我的代码以(希望)防止此错误。

谁能解释一下如何实现这一点?

I'm getting an OutOfMemoryException:

E/AndroidRuntime( 3013): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
E/AndroidRuntime( 3013):        at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime( 3013):        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:375)
E/AndroidRuntime( 3013):        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:394)

In the following function:

static Bitmap downloadBitmap(String url)
    {
        final HttpClient client = new DefaultHttpClient();
        final HttpGet getRequest = new HttpGet(url);

        try 
        {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();

            // Check HTTP Status code
            if (statusCode != HttpStatus.SC_OK)
            { 
                debugPrint("ImageDownloader StatusCode Error " + statusCode + " while retrieving bitmap from " + url);
                return null;
            }
            else;


            final HttpEntity entity = response.getEntity();

            if (entity != null)
            {
                InputStream inputStream = null;
                try
                {
                    inputStream = entity.getContent(); 
                    if( inputStream == null)
                    {
                        debugPrint("ImageDownloader::downloadBitmap() - INPUTSTREAM = NULL!!!!!!");
                    }
                    else;



                    // THIS LINE IS GIVING THE ERROR
                    final Bitmap bitmap = BitmapFactory.decodeStream( new FlushedInputStream(inputStream));

                    if( bitmap == null)
                    {
                        debugPrint("LocrPhoto::downloadBitmap() - about to return BITMAP =NULL!!!!!!");
                    }
                    else;

                    return bitmap;
                }
                catch (Exception e)
                {
                    // Could provide a more explicit error message for IOException or IllegalStateException
                    getRequest.abort();
                    debugPrint("LocrPhoto::downloadBitmap() Error while decoding bitmap from " + url + "\n"+ e.toString());
                }
                finally
                {
                    if (inputStream != null)
                    {
                        inputStream.close();  
                    }
                    entity.consumeContent();
                }
            }
            else
            {
                debugPrint("LocrPhoto::downloadBitmap("+url+") - entity = NULL!!!!!");
            }
        }
        catch (Exception e)
        {
            // Could provide a more explicit error message for IOException or IllegalStateException
            //getRequest.abort();
            debugPrint("LocrPhoto::downloadBitmap() Error while retrieving bitmap from " + url + "\n"+ e.toString());
        }
        finally
        {
            if (client != null)
            {
                // CLOSE CONNECTION
            }
        }
        debugPrint("LocrPhoto::downloadBitmap("+url+") - returning NULL at end of function");
        return null;
    }

FlushedInputStream (though I got the error before adding this code):

// A Class to hopefully avoid the BitmapFactory.decodeStream() returning null bug
    //      http://code.google.com/p/android/issues/detail?id=6066
    static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

        @Override
        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L) {
                      int byt = read();
                      if (byt < 0) {
                          break;  // we reached EOF
                      } else {
                          bytesSkipped = 1; // we read one byte
                      }
               }
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }

Basically, I have an activity that downloads images, places them in a framelayout and fades frames in and out to give a slideshow. The framelayout has two imageview children.

I've seen people speak of SoftReference being used to prevent OOMExceptions, but I can't understand how this would be applied to my code to (hopefully) prevent this error.

Could anyone explain how this might be achieved?

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

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

发布评论

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

评论(1

┼── 2024-10-21 13:59:46

我正在处理与您相同的问题,我发现问题是 BitmapFactory.decodeStream 的内存消耗(如日志所述)。您所要做的就是在调用 BitmapFactory.decodeStream 之前缩放位图,您可以找到一篇非常好的文章来解决您的问题!

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

希望有帮助!

I was dealing with the same problem as you and I found that the problem is the memory consumption of the BitmapFactory.decodeStream (as the log says). What you have to do is scale your bitmap just before the call of BitmapFactory.decodeStream, you can find a very nice article that will resolve your problem!

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

Hope it helps!

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