2015-10-18 24 views
1

在將背景圖像設置爲Android視圖(API 22)的過程中,我遇到了一些問題。高效設置Android視圖背景圖像給出java.lang.OutOfMemoryError

我的照片是1MB .jpeg文件,4000x2672。

起初我經由

android:background="@drawable/your_image" 

方法嘗試,得到一個d/Skia的:---分配失敗了縮放的位圖錯誤。

然後我也跟着http://developer.android.com/training/displaying-bitmaps/load-bitmap.html並執行如下它:

BitmapDecoder.java

(..omissis..) 
public class BitmapDecoder { 

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

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    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; 
    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); 
} 

}

SplasActivity.java(主要活動)

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_splash); 
    LinearLayout mL = (LinearLayout)findViewById(R.id.MainLayout); 
    Display display = getWindowManager().getDefaultDisplay(); 
    Point size = new Point(); 
    display.getSize(size); 
    int width = size.x; 
    int height = size.y; 

    if (Build.VERSION.SDK_INT >= 16) { 
     Drawable d = new BitmapDrawable(getResources(), 
       BitmapDecoder.decodeSampledBitmapFromResource(getResources(), 
         R.drawable.andromeda, 
         1080,1920)); 
     mL.setBackground(d); 
    } 

    this.getSupportActionBar().hide(); 
} 

我獲得設備屏幕的WxH,調整Drawable資源的大小e轉換爲該尺寸,將生成的位圖轉換爲Drawable,將Drawable設置爲View背景。

但我總是得到

D/skia﹕ --- allocation failed for scaled bitmap
...
java.lang.OutOfMemoryError: Failed to allocate a 684032012 byte allocation with 16777120 free bytes and 227MB until OOM

錯誤。

我一直在尋找幾小時,並實施所有建議的技術,沒有運氣。作爲一個側面說明,如果我把寬度和高度設置爲一個非常小的值(例如400x200),它就可以工作。但是,正如你所想象的那樣,這是不可行的。

關於如何解決任何想法?

+0

?從logcat發佈stacktrace,'calculateInSampleSize'返回什麼? – pskink

+0

stacktrace from logcat:http://pastebin.com/2nxTDjLb –

+0

calculateInSampleSize返回1,屏幕分辨率爲1440 x 2560(Samsung Galaxy S6) –

回答

2

判斷從你的號碼,你已經把你的JPEG在res/drawable文件夾是一樣res/drawable-mdpi,補救方法是將其放置在res/drawable-nodpi文件夾

要分配684 MB的圖像
0

我認爲問題在於您以壓縮的jpeg格式(1MB)評估圖像大小,但是當您將它加載並操作到您的軟件中時,它將以其位圖形式解壓縮。

正如您在提及的鏈接中所報告的: 「...較低分辨率的版本應該與顯示它的UI組件的大小相匹配,分辨率較高的圖像不會提供任何明顯的好處,但仍然佔用「 ..」

您正在使用4000x2672 = 10688000像素的圖像,並且每個像素都需要多個字節來編碼顏色,因此分配了684032012個分量字節。

我可以給出的唯一建議是評估你想要顯示圖像的大屏幕是什麼,檢查它的定義並重新調整圖像以便最多匹配該值。

+0

684032012/10688000 = 64(64.0000011227545),所以它使用每像素64字節? – pskink

+0

不一定,實際上我沒有檢查用於顏色編碼的實際字節數是多少,這就是爲什麼我沒有在我的回覆中指定任何其他數值。無論如何,所需內存的一部分被用來重新調整和適應遠大的圖像到小屏幕。我的目的只是爲了表明圖像比需要的更大,而不是調查細節。 – Chosmos

+0

,那是罪魁禍首。實際使用的圖像的大小不是4000x2672。 –