2013-03-20 173 views
2

我有一個關於1948X674尺寸和104kb大小的圖像。它給三星Galaxy S3上的OutOfMemoryError。我在水平滾動視圖中顯示此圖像。 這裏是我的xml增長堆大小和OutOfMemory錯誤

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".Panorama" > 

    <HorizontalScrollView 
     android:id="@+id/hscroll" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_above="@+id/tapToEnter" 
     android:scrollbars="none" > 

     <ImageView 
      android:id="@+id/imgPanorama" 
      android:layout_width="wrap_content" 
      android:layout_height="match_parent" /> 
    </HorizontalScrollView> 

    <Button 
     android:id="@+id/tapToEnter" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:text="Tap to enter" /> 

</RelativeLayout> 

,我編程設定畫面吧。 decodeSampledBitmapFromResource()我使用從Loading Large Bitmap Efficiently

Bitmap bmp; 
try 
     { 
     BitmapDrawable bd=(BitmapDrawable)getResources().getDrawable(R.drawable.panorama); 
     reqwidth=bd.getIntrinsicWidth(); 
     reqheight = bd.getIntrinsicHeight(); 
     }catch(OutOfMemoryError oom) 
     { 
      oom.printStackTrace(); 
     } 
bmp=decodeSampledBitmapFromResource(getResources(),R.drawable.panorama, reqwidth, reqheight); 
imgPanorama.setImageBitmap(bmp); 




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) { 

      // Calculate ratios of height and width to requested height and width 
      final int heightRatio = Math.round((float) height/(float) reqHeight); 
      final int widthRatio = Math.round((float) width/(float) reqWidth); 

      // Choose the smallest ratio as inSampleSize value, this will guarantee 
      // a final image with both dimensions larger than or equal to the 
      // requested height and width. 
      inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
     } 

     return inSampleSize; 
    } 
    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
      int reqWidth, int reqHeight) { 

     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     options.inPurgeable=true; 
     /*options.inDither=false;      //Disable Dithering mode 
     options.inPurgeable=true;     //Tell to gc that whether it needs free memory, the Bitmap can be cleared 
     options.inInputShareable=true;    //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future 
     options.inTempStorage=new byte[32 * 1024]; 
     */ 
     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); 
    } 


@Override 
    protected void onDestroy() { 
     // TODO Auto-generated method stub 
     super.onDestroy(); 
     if(bmp!=null && !bmp.isRecycled()) 
     { 
      bmp.recycle(); 
      bmp=null; 

     } 
    } 

這是我的logcat,當我開始活動。

03-20 11:20:36.175: I/dalvikvm-heap(30452): Grow heap (frag case) to 17.982MB for 5251824-byte allocation 
03-20 11:20:36.260: I/dalvikvm-heap(30452): Grow heap (frag case) to 38.014MB for 21007248-byte allocation 
03-20 11:20:36.385: I/dalvikvm-heap(30452): Grow heap (frag case) to 38.016MB for 5251824-byte allocation 
03-20 11:20:36.480: I/dalvikvm-heap(30452): Grow heap (frag case) to 58.050MB for 21007248-byte allocation 

回答

2

Bitmap.recycle()是你的朋友,因爲它可以將畫面的像素數據被更快地釋放比手動或自動垃圾收集會做同樣的工作。因此,當你完成一個大的圖像時,在允許它超出範圍之前,它可能是一個好主意。當然它會在超出範圍後自動收集垃圾,但recycle()會立即釋放Bitmap所使用的絕大部分內存。

例如,您可以複製Bitmap的UI元素後選擇recycle()

Bitmap bmp; 
bmp=decodeSampledBitmapFromResource(getResources(),R.drawable.panorama, reqwidth, reqheight); 
imgPanorama.setImageBitmap(bmp); 

// Free the pixel data immediately in order to keep heap from growing out of control. 
// This is especially useful while displaying multiple images. 
bmp.recycle(); 

您也可以嘗試用reqwidthreqheight較小的值,這將允許更大的計算inSampleSize讓您Bitmap將會使用更少的內存。

+0

好像你說的試過回收位圖。它給錯誤就像不能使用已經回收的位圖。 – Manoj 2013-03-20 07:34:07

+0

除了像'getWidth()'和'getHeight()'之類的非像素訪問函數,'bmp.recycle()'調用之後,不能使用圖像'bmp'等。如果在'setImageBitmap )',然後移動'bmp.recycle()'調用。 – 2013-03-20 07:39:06

+0

你是對的我正在使用高度和寬度函數看到上面的代碼。我在Destroy()中回收它。 – Manoj 2013-03-20 08:03:57