2011-12-23 37 views
4

我正在一個應用程序,其中我有圖像被異步下載幻燈片。一張幻燈片包含10張幻燈片,因此在打開幻燈片時會下載10張圖像。在我滾動10-15幻燈片後,大約我開始獲取內存警告,並跟蹤跟蹤和應用程序崩潰中的異常。內存不足例外,當處理位圖

這裏是跟蹤:

12-23 12:23:53.124: ERROR/dalvikvm-heap(3067): 45850-byte external allocation too large for this process. 
12-23 12:23:53.134: ERROR/dalvikvm(3067): Out of memory: Heap Size=13127KB, Allocated=11913KB, Bitmap Size=11407KB 
12-23 12:23:53.134: ERROR/GraphicsJNI(3067): VM won't let us allocate 45850 bytes 
12-23 12:23:53.134: DEBUG/skia(3067): --- decoder->decode returned false 
12-23 12:23:53.134: WARN/dalvikvm(3067): threadid=46: thread exiting with uncaught exception (group=0x400259f8) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067): FATAL EXCEPTION: Thread-1016 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:468) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:332) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at com.nbcu.myApp.appsupport.AsyncImageLoader.loadImageFromUrl(AsyncImageLoader.java:98) 
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):  at com.nbcu.myApp.appsupport.AsyncImageLoader$2.run(AsyncImageLoader.java:70) 
12-23 12:23:53.154: WARN/ActivityManager(96): Force finishing activity com.nbcu.myApp.activities/com.nbcu.myApp.controllers.StoriesListController 
12-23 12:23:53.224: ERROR/dalvikvm-heap(3067): 45850-byte external allocation too large for this process. 
12-23 12:23:53.234: DEBUG/SurfaceFlinger(96): Layer::setBuffers(this=0x2fabc0), pid=96, w=1, h=1 
12-23 12:23:53.234: ERROR/dalvikvm(3067): Out of memory: Heap Size=13127KB, Allocated=11948KB, Bitmap Size=11407KB 
12-23 12:23:53.234: ERROR/GraphicsJNI(3067): VM won't let us allocate 45850 bytes 
12-23 12:23:53.234: ERROR/Error(3067): Message = java.lang.OutOfMemoryError: bitmap size exceeds VM budget 

其中正在下載圖像的代碼是:

public void run() { 

     Looper.prepare(); 
     for (int i = 0; i < slides.size(); i++) { 
      try { 

       final SlideShowItem story = slides.get(i); 
       if (story.getImage() == null) { 
        Drawable cachedImage = Utils.database.getRSSImage(Constants.StoriesTable, story.getItemId()); 

        if (cachedImage != null) { 
         story.setImage(cachedImage); 

        } else { 
         cachedImage = asyncImageLoader.loadDrawable(story.getImagePath(), new ImageCallback() { 
          public void imageLoaded(Drawable imageDrawable, String imageUrl) { 


           story.setImage(imageDrawable); 
           Utils.database.storeRSSItemImage(Constants.StoriesTable, imageDrawable, story.getItemId()); 
          } 
         }); 
        } 
       } 

       Thread.sleep(500); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     Looper.loop(); 
    } 

代碼loadDrawable()是:

public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) { 

    final Handler handler = new Handler() { 

     public void handleMessage(Message message) { 

      imageCallback.imageLoaded((Drawable) message.obj, imageUrl); 
     } 
    }; 
    new Thread() { 

     public void run() { 

       Drawable drawable = loadImageFromUrl(imageUrl); 
       // System.out.println("image url: " + imageUrl); 
       if (drawable != null) 
       { 
        Message message = handler.obtainMessage(0, drawable); 
        handler.sendMessage(message); 
       } 
     } 

    }.start(); 
    return null; 
} 

,對於編碼loadImageFromURL()是:

public static Drawable loadImageFromUrl(String url) { 

    Drawable image = null; 

    try { 
     InputStream in = (java.io.InputStream) new java.net.URL(url).getContent(); 
     if (in != null) { 
      image = Drawable.createFromStream(in, "image"); 
     } 
     in.close(); 

    } catch (Exception ex) { 
     // ex.printStackTrace(); 
     Log.v("Exception ", "Asyn Image.In LoadImageFromURL Message: " + ex.toString()); 

    } 
    return image; 
} 

一旦下載圖像,它們就會被緩存。我無法找到避免此異常的解決方法。可能是什麼原因?我也試圖設置圖像視圖null當活動被破壞,但它沒有爲我做什麼?任何幫助表示讚賞。提前致謝。

+0

解碼函數是否在流中包含任何其他資源? 究竟在哪裏拋出錯誤? – 2011-12-23 07:59:36

回答

5

Android是一個移動操作系統。它的內存有限,所以你不能緩存所有的slides.size()。我假設大小> 15.例如,即時通訊運行FastCV算法與高清圖像作爲標記,250000 x 180000像素,如果我在PC上運行該程序,工作正常,如果我在手機上不做,因爲內存不夠。

我認爲你可以解決問題,如果只有caché10 - 15圖像,取決於它們的大小。如果滾動,然後在已經使用的內存中緩存新的內容。

2

你應該使用一種調整lazy initialization。我會一次使用3張圖像,當前顯示的圖像和接下來的兩張。這樣,當用戶正在查看image1時,image2和image3已經在內存中。當用戶滑動到image2時,image4應該加載到先前的image1緩衝區中(image3仍在內存中) 我希望這有助於

4

考慮將緩存圖像縮小到它們所用視圖的大小。例如,您可以在您的loadImageFromUrl(String url)方法中使用以下方法:

// Determining the original size of the image: 
BitmapFactory.Options optnsSizeOnly = new BitmapFactory.Options(); 
optnsSizeOnly.inJustDecodeBounds = true; 
InputStream inputStreamSizeOnly = (java.io.InputStream) new java.net.URL(url).getContent(); 
BitmapFactory.decodeStream(inputStreamSizeOnly, null, optnsSizeOnly); 
int widthOriginal = optnsSizeOnly.outWidth; 

// Determining the scale ratio. 
// Note, it's just an example, you should use more sophisticated algorithm: 
int ratio = widhtOriginal/widthView; // widthView is supposed to be known 

// Now loading the scaled image: 
BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize = ratio; 

InputStream inputStream = (java.io.InputStream) new java.net.URL(url).getContent(); 
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);