2016-08-24 45 views
0

我使用eclipse開發一款Android遊戲,我有很多的資源和它的圖像,使用SDP大小單位大小的圖像,並期待罰款,所有設備:機器人 - 堆大小錯誤

https://github.com/intuit/sdp

另外畢加索圖書館將圖像加載到圖像上,

主要問題是,在某些設備中,我得到堆外大小內存錯誤。

問題是,我是否必須在子文件夾中爲ldpi,mdpi等聲明不同大​​小的不同圖像...即使我使用Sdp和Picasso?

回答

0

Android在加載大背景或大量圖片時,往往會導致內存溢出(Out of Memory Error),基於我處理過這些問題和其他開發人員的經驗,整理解決方案的經驗如下(部分代碼和文本源無法驗證):

選項一,提請注意讀取圖像的方法,適當壓縮 儘量不要使用setImageResource setImageBitmap BitmapFactory.decodeResource或設置一個大圖像,因爲這些函數在完成解碼之後,最終由createBitmap java層來完成,需要消耗更多的內存。 取而代之,使用第一種方法由BitmapFactory.decodeStream創建一個位圖,然後將其設置爲ImageView的源,decodeStream最大的祕密在於它直接調用JNI >> nativeDecodeAsset()來完成解碼,不再需要使用createBitmap java層,從而節省空間java層。

InputStream is = this.getResources() openRawResource (R.drawable.pic1).; 

    BitmapFactory.Options options = new BitmapFactory.Options(); 

    options.inJustDecodeBounds = false; 

    options.inSampleSize = 10; // width, hight to a tenth of the original 

    Bitmap btp = BitmapFactory.decodeStream (is, null, options); 

如果我們在讀取時添加Config參數圖像,它可以有效地減少帶內存的負載,從而有效地防止拋出內存異常。

/**

* In most provinces memory reads local resources image 

* @param Context 

* @param ResId 

* @return 

*/

public static Bitmap readBitMap (Context context, int resId) { 

    BitmapFactory.Options opt = new BitmapFactory.Options(); 

    opt.inPreferredConfig = Bitmap.Config.RGB_565; 

    opt.inPurgeable = true; 

    opt.inInputShareable = true; 

    // Get the resource image 

    . InputStream is = context.getResources() openRawResource (resId); 

    return BitmapFactory.decodeStream (is, null, opt); 

    } 

此外,decodeStream拍照直接讀取字節碼,而不是根據機器的各種分辨率自動適應,然後使用decodeStream,需要HDPI和MDPI,LDPI配置對應圖像資源,或在不同的分辨率機器是相同的大小(像素數),顯示的大小是不正確的。

方案二,當內存映像 典型的活動或適當和及時的恢復片段的onStop /圖片的onDestroy時,你可以釋放資源:

如果(ImageView的= NULL & & imageView.getDrawable()! = NULL){

Bitmap oldBitmap = ((BitmapDrawable) imageView.getDrawable()) getBitmap().; 

    imageView.setImageDrawable (null); 

    if (oldBitmap! = null) { 

     oldBitmap.recycle(); 

     oldBitmap = null; 

    } 

}

//其他代碼。

System.gc();

在釋放資源時,需要注意釋放相關的Drawable Bitmap或者是否有對其他類的引用。如果正常調用,則可以使用Bitmap。isRecycled()方法確定是否有明顯的恢復;如果UI線程接口相關的代碼使用它,則需要注意避免可能的資源回收使用,或者可能導致系統異常: E/AndroidRuntime:java.lang.IllegalArgumentException:Can not繪製回收的位圖 而且無法有效捕獲和處理異常。

選項三,在加載完整圖像時避免不必要 只需要知道圖像大小的情況下,不能將圖像完整加載到內存中。 使用BitmapFactory對圖像進行壓縮時,BitmapFactory.Options在將JDeveloDeDebug設置爲true後,再使用decodeFile()等方法,可以計算圖片在處於未分配空間狀態時的大小。示例:

BitmapFactory.Options opts = new BitmapFactory.Options();

//設置爲true inJustDecodeBounds

opts.inJustDecodeBounds = TRUE;

//使用decodeFile獲得的圖像的寬度和高度

BitmapFactory.decodeFile(路徑,選擇採用);

//打印出來的畫面寬度和高度

Log.d( 「示例」,opts.outWidth + 「」 + opts.outHeight); (PS:事實上,標題信息由基本圖像信息的圖像讀出的原理)

方案四,優化的Dalvik虛擬機的堆內存分配 堆(堆)是一個VM存儲器在大多數情況下,通常動態分配。堆大小不是靜態的,通常有一個分配機制來控制其大小。例如,初始HEAP爲4M大,當佔用4M空間超過75%時,重新分配堆大8M;當8M被佔用超過75%時,分配堆是16M大。顛倒過來,當16M堆使用不到30%時,其尺寸減小8M大。重置堆大小,尤其是壓縮時,通常與內存複製有關,所以更改堆大小會對效率產生不利影響。 堆利用率堆利用率。當此實際利用率偏離此時,虛擬內存堆大小調整GC中的時間,因此實際佔用率更接近百分比。 setTargetHeapUtilization方法dalvik.system.VMRuntime類可以提供增強的處理效率程序堆內存。

private final static float TARGET_HEAP_UTILIZATION = 0.75f;

//當程序可以調用的onCreate

VMRuntime.getRuntime()setTargetHeapUtilization(TARGET_HEAP_UTILIZATION).;

方案五,自定義堆(堆)內存大小 對於一些Android的項目,影響性能的瓶頸主要是Android的自身內存管理問題,目前的手機廠商對於軟件的流暢度比較小氣RAM是影響非常敏感關於RAM的性能,除了優化Dalvik VM堆內存的外部賦值之外,我們還可以定義自己的軟件來強制內存大小,我們使用dalvik.system。VMRuntime類提供Dalvik來設置最小堆內存,例如:

private final static int CWJ_HEAP_SIZE = 6 * 1024 * 1024;

VMRuntime.getRuntime()setMinimumHeapSize(CWJ_HEAP_SIZE);. //設置最小堆內存大小爲6MB。

不過,上面的方法還是有問題的,其實只是改變函數setMinimumHeapSize堆的下限,它可以防止堆內存分配太頻繁,當設置最小堆大小超過上限(Max Heap Size ),同時仍然使用堆棧限制,因爲內存不足沒有效果。

最後,告訴我們關於圖片佔用內存算法的過程。 android在基類中的圖像處理是Bitmap,按照定義,是一個位圖。內存密集型算法,如:圖像寬度*高度*配置。 如果Config設置爲ARGB_8888,則上面的Config爲4. 480 * 320圖像內存使用量爲480 * 320 * 4字節。 默認情況下android內存佔用的進程爲16M,由於他所持有的Bitmap除了java數據之外,底層的C++圖形庫將持有skia SKBitmap對象,因此一般建議內存的圖片大小不應超過8M。這是可以調整的,你可以在編譯源代碼的時候設置參數。