2013-08-20 56 views
0

當我有相當多的結果返回時(好到約30),我正在解決內存問題。實際的錯誤是:內存不足問題

08-20 10:55:19.820: E/dalvikvm-heap(13483): Out of memory on a 499408-byte allocation. 
08-20 10:55:19.835: E/AndroidRuntime(13483): FATAL EXCEPTION: main 
08-20 10:55:19.835: E/AndroidRuntime(13483): java.lang.OutOfMemoryError 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:650) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:389) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at com.directenquiries.assessment.tool.Globals.Functions.decodeSampledBitmapFromFile(Functions.java:94) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at com.directenquiries.assessment.tool.db.assets.AssetRow.image(AssetRow.java:119) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at com.directenquiries.assessment.tool.ViewAssetsList.loadTable(ViewAssetsList.java:75) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at com.directenquiries.assessment.tool.ViewAssetsList.onResume(ViewAssetsList.java:60) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1188) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.app.Activity.performResume(Activity.java:5280) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2606) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2644) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.os.Handler.dispatchMessage(Handler.java:99) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.os.Looper.loop(Looper.java:137) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at android.app.ActivityThread.main(ActivityThread.java:4898) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at java.lang.reflect.Method.invokeNative(Native Method) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at java.lang.reflect.Method.invoke(Method.java:511) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 
08-20 10:55:19.835: E/AndroidRuntime(13483): at dalvik.system.NativeStart.main(Native Method) 

圖像被縮小的方法是:

public static Bitmap decodeSampledBitmapFromFile(String imagePath, int reqWidth, int reqHeight) { 

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

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

     // Decode bitmap with inSampleSize set 
     options.inJustDecodeBounds = false; 
     return BitmapFactory.decodeFile(imagePath, options); 
    } 

的圖像出來的DB和設置,如:

@Override 
     public String imagePath() { 
       if (firstissuePhoto == null) { 
        firstissuePhoto = StationPhotoDB.getFirstPhotoWithStationObjectID(this.stationObjectID);  
         if(!firstissuePhoto.endsWith("jpg")){ 
          firstissuePhoto = "notset"; 
         } 
       } 
       return firstissuePhoto; 

     } 



    @Override 
    public Bitmap image() { 
     if (firstissuePhotoThumb == null) { 
      firstissuePhotoThumb = Functions.decodeSampledBitmapFromFile(imagePath(),200, 200); 
     } 
     return firstissuePhotoThumb; 
    } 

然後,當我真正使用圖像,並設置它,就像:

String picturePath = dbRow.imagePath(); 
if (picturePath.equals("notset")) { 
      holder.ivPicture.setImageResource(R.drawable.photonotset);  
     } else { 
      holder.ivPicture.setImageBitmap(dbRow.image());    
      } 

編輯:繼承所需的例程:

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) { 
      if (width > height) { 
       inSampleSize = Math.round((float)height/(float)reqHeight); 
      } else { 
       inSampleSize = Math.round((float)width/(float)reqWidth); 
      } 
     } 
     return inSampleSize; 
    } 
+0

post calculateInSampleSize – Blackbelt

+0

當你在內存中保存太多的位圖對象時,可能會發生OutOfMemoryError .. –

+0

我已經添加了calucluteinsamplesize,乾杯 – TMB87

回答

0

您需要回收未使用的位圖。有一個回收()api。使用它

+0

你介意再詳細一點嗎?我將在什麼階段回收? – TMB87

+0

當你不再需要時,會在Bitmap對象上調用'recycle'。因此,您需要將Bitmap與持有者相關聯,然後在設置圖像之前執行'if(holder.image!= null)holder.image.recycle();'。這隻會確保圖像被垃圾收集,並不會真正幫助OOM,除非您創建了很多位圖。添加'Log'跟蹤應該有助於這個。請參閱http://stackoverflow.com/questions/3823799/android-bitmap-recycle-how-does-it-work。 – reece

+0

你也可以參考這個鏈接,希望它有幫助http://stackoverflow.com/questions/4959485/bitmap-bitmap-recycle-weakreferences-and-garbage-collection –

0

該代碼看起來是正確的,並遵循Android最佳實踐來處理大型位圖文件。

看着堆棧跟蹤,內存不足發生在BitmapFactory.nativeDecodeStream。使用JPEG圖像時,應用程序必須解碼(解壓縮)圖像數據。該解壓縮可能需要在縮放之前將圖像解壓縮到內存中。如果圖像很大(例如照片),這可能很容易需要大量的內存。

你可能想嘗試迫使inSampleSize是8的倍數爲JPEG圖像可以有8個或16這樣的塊大小可以幫助圖像縮放邏輯沒有使用太多內存的JPEG解碼。

另外,記錄width,heightinSampleSize值應該是有用的。