2012-11-02 77 views
1

我有一個簡單的問題:雖然我正確使用了sampleSize,但我的代碼甚至沒有達到BitmapFactory代碼,因爲DefaultHttpClient已經在拋出異常。OutOfMemoryError通過DefaultHttpClient加載位圖

這裏是我的代碼:

   DefaultHttpClient client = new DefaultHttpClient(); 
       HttpGet request = new HttpGet(mSongInfo.imageLarge); 
       HttpResponse response = client.execute(request); 
       int sampleSize = 1; 
       while (response.getEntity().getContentLength()/sampleSize 
         /sampleSize > 100 * 1024) { 
        sampleSize *= 2; 
       } 
       BitmapFactory.Options options = new BitmapFactory.Options(); 
       options.inSampleSize = sampleSize; 
       final Bitmap bitmap = BitmapFactory.decodeStream(response 
         .getEntity().getContent(), null, options); 

這裏是例外:

0 java.lang.OutOfMemoryError: (Heap Size=11463KB, Allocated=7623KB, Bitmap Size=9382KB) 
1  at org.apache.http.util.ByteArrayBuffer.<init>(ByteArrayBuffer.java:53) 
2  at org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:82) 
3  at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:98) 
4  at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83) 
5  at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170) 
6  at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106) 
7  at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129) 
8  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:173) 
9  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
10  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
11  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359) 
12  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
13  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
14  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
15  at de.goddchen.android.easysongfinder.fragments.SongFragment$1.run(SongFragment.java:79) 
16  at java.lang.Thread.run(Thread.java:1027) 

正如你看到的,代碼甚至沒有達到其中i檢查大小的部分(內容 - 長度)並計算適當的樣本大小。

我不知道簡單地調用DefaultHttpClient.execute(...)已經將完整的內容加載到內存中。

我做錯了什麼?首先檢索內容長度然後開始閱讀InputStream的內容的正確方法是什麼?

編輯 避免常見的答案來說明如何從URL加載圖像:我已經知道該怎麼做,我也貼上面的代碼,那麼爲什麼你一直對參考教程?我明確地明確了這個問題:爲什麼HttpClient.execute(...)已經獲取了整個內容並將其存儲在內存中,而不是向我提供合適的InputStream?請不要發佈任何關於如何從URL加載Bitmap的初學者教程...

+0

是包括'內容Length'頭的HTTP響應?你測試了什麼環境(設備與模擬器,操作系統版本等)? – CommonsWare

+0

是的,它提供了適當的內容長度。我正在從薑餅到果凍豆等真實設備收到這些錯誤...... – Goddchen

回答

1

只需使用HttpUrlConnection即可獲得該簡單請求。

此外,您在確定樣本大小的方式是駭人聽聞,解碼到Bitmap之前的內容大小不是確定Bitmap字節分配的好方法,請使用它的大小。

+0

HttpUrlConnection是否提供了正確的InputStream並且不立即將所有內容都存儲在內存中 – Goddchen

+0

是的,同時請記下您的樣本量確定 –

+0

是的我知道樣本量問題,但獲得維度需要讀取流兩次(一次inJustDecodeBounds,然後再次使用正確的inSampleSize)。這是不可接受的。所以我是粗略猜測圖像的內容長度 – Goddchen

0

我有一個類似的問題,從互聯網加載的圖像和我解決這個問題的方式是將圖像保存在臨時位置手機(您可以使用內部或外部存儲,無所謂)並從那裏加載圖像。將圖像字節保存在文件中,使用緩衝區,不要在單個操作中讀寫所有字節。

這種方式工作正常。我現在沒有示例代碼,我沒有找到我使用這種技術的項目,但是你可以使用谷歌的方式來保存來自http的二進制資源。

後來編輯: 另一個類似的問題在這裏問:Regarding download image from url in android

後來的後來編輯

這個流不能被多次讀取,在第一次讀取獲取圖像的大小和在此之後去採取另一個信息。這是你錯誤的簡短解釋。編譯器優化你的代碼,以便能夠從流中重新讀取並將其放到內存中。當發生這種情況時,OOM被拋出。

+0

如果圖像在從HTTP響應流中加載時會引發OOM,那麼在將其存儲在磁盤上後,它將一如既往地讀取。使用BitmapFactory.Options調整圖像的大小時,實際將其讀入內存中就像這裏所說:http://stackoverflow.com/a/8497703/939023 –

+0

當您從HTTP讀取資源時,會讀取所有字節,然後嘗試解碼圖像。只需保存圖像,使用緩衝區,讓我們說1k緩衝區。你贏了;沒有任何OOM例外。 –

+0

shivan,我正在使用BitmapFactory.Options.inSampleSize,就像你在代碼中看到的那樣。儘管這段代碼從來沒有達到,因爲HttpClient似乎在調用執行(...)時將完整的內容加載到內存中。這是實際的問題。 – Goddchen

相關問題