1. 程式人生 > >Android OOM的解決方案

Android OOM的解決方案

儘量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource來設定一張大圖,
因為這些函式在完成decode後,最終都是通過java層的createBitmap來完成的,需要消耗更多記憶體。


因此,改用先通過BitmapFactory.decodeStream方法,創建出一個bitmap,再將其設為ImageView的 source,
decodeStream最大的祕密在於其直接呼叫JNI>>nativeDecodeAsset()來完成decode,
無需再使用java層的createBitmap,從而節省了java層的空間。
如果在讀取時加上圖片的Config引數,可以跟有效減少載入的記憶體,從而跟有效阻止拋out of Memory異常
另外,decodeStream直接拿的圖片來讀取位元組碼了, 不會根據機器的各種解析度來自動適應, 
使用了decodeStream之後,需要在hdpi和mdpi,ldpi中配置相應的圖片資源, 
否則在不同解析度機器上都是同樣大小(畫素點數量),顯示出來的大小就不對了。


另外,以下方式也大有幫助:
1. InputStream is = this.getResources().openRawResource(R.drawable.pic1);
     BitmapFactory.Options options=new BitmapFactory.Options();
     options.inJustDecodeBounds = false;
     options.inSampleSize = 10;   //width,hight設為原來的十分一
     Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2. if(!bmp.isRecycle() ){
         bmp.recycle()   //回收圖片所佔的記憶體
         system.gc()  //提醒系統及時回收
}


以下奉上一個方法:


Java程式碼


   1. /**
   2.  * 以最省記憶體的方式讀取本地資源的圖片
   3.  * @param context
   4.  * @param resId
   5.  * @return
   6.  */  
   7. public static Bitmap readBitMap(Context context, int resId){  
   8.     BitmapFactory.Options opt = new BitmapFactory.Options();  
   9.     opt.inPreferredConfig = Bitmap.Config.RGB_565;   
  10.     opt.inPurgeable = true;  
  11.     opt.inInputShareable = true;  
  12.        //獲取資源圖片  
  13.     InputStream is = context.getResources().openRawResource(resId);  
  14.         return BitmapFactory.decodeStream(is,null,opt);  
  15. }




================================================================================
Android記憶體溢位的解決辦法


轉自:http://www.cppblog.com/iuranus/archive/2010/11/15/124394.html?opt=admin


昨天在模擬器上給gallery放入圖片的時候,出現java.lang.OutOfMemoryError: bitmap size exceeds VM budget 異常,影象大小超過了RAM記憶體。
      模擬器RAM比較小,只有8M記憶體,當我放入的大量的圖片(每個100多K左右),就出現上面的原因。
由於每張圖片先前是壓縮的情況,放入到Bitmap的時候,大小會變大,導致超出RAM記憶體,具體解決辦法如下:


//解決載入圖片 記憶體溢位的問題
                    //Options 只儲存圖片尺寸大小,不儲存圖片到記憶體
                BitmapFactory.Options opts = new BitmapFactory.Options();
                //縮放的比例,縮放是很難按準備的比例進行縮放的,其值表明縮放的倍數,SDK中建議其值是2的指數值,值越大會導致圖片不清晰
                opts.inSampleSize = 4;
                Bitmap bmp = null;
                bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts);                             


                ...              


               //回收
                bmp.recycle();


通過上面的方式解決了,但是這並不是最完美的解決方式。


通過一些瞭解,得知如下:


優化Dalvik虛擬機器的堆記憶體分配


對 於Android平臺來說,其託管層使用的Dalvik Java VM從目前的表現來看還有很多地方可以優化處理,比如我們在開發一些大型遊戲或耗資源的應用中可能考慮手動干涉GC處理,使用 dalvik.system.VMRuntime類提供的setTargetHeapUtilization方法可以增強程式堆記憶體的處理效率。當然具體 原理我們可以參考開源工程,這裡我們僅說下使用方法:   private final static float TARGET_HEAP_UTILIZATION = 0.75f; 在程式onCreate時就可以呼叫 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。




Android堆記憶體也可自己定義大小


    對於一些Android專案,影響效能瓶頸的主要是Android自己記憶體管理機制問題,目前手機廠商對RAM都比較吝嗇,對於軟體的流暢性來說RAM對 效能的影響十分敏感,除了 優化Dalvik虛擬機器的堆記憶體分配外,我們還可以強制定義自己軟體的對記憶體大小,我們使用Dalvik提供的 dalvik.system.VMRuntime類來設定最小堆記憶體為例:


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


VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //設定最小heap記憶體為6MB大小。當然對於記憶體吃緊來說還可以通過手動干涉GC去處理




bitmap 設定圖片尺寸,避免 記憶體溢位 OutOfMemoryError的優化方法
★android 中用bitmap 時很容易記憶體溢位,報如下錯誤:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget


● 主要是加上這段:
BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;


● eg1:(通過Uri取圖片)
private ImageView preview;
BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = 2;//圖片寬高都為原來的二分之一,即圖片為原來的四分之一
                    Bitmap bitmap = BitmapFactory.decodeStream(cr
                            .openInputStream(uri), null, options);
                    preview.setImageBitmap(bitmap);
以上程式碼可以優化記憶體溢位,但它只是改變圖片大小,並不能徹底解決記憶體溢位。
● eg2:(通過路徑去圖片)
private ImageView preview;
private String fileName= "/sdcard/DCIM/Camera/2010-05-14 16.01.44.jpg";
BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;//圖片寬高都為原來的二分之一,即圖片為原來的四分之一
                        Bitmap b = BitmapFactory.decodeFile(fileName, options);
                        preview.setImageBitmap(b);
                        filePath.setText(fileName);


★Android 還有一些效能優化的方法:
●  首先記憶體方面,可以參考 Android堆記憶體也可自己定義大小 和 優化Dalvik虛擬機器的堆記憶體分配


●  基礎型別上,因為Java沒有實際的指標,在敏感運算方面還是要藉助NDK來完成。Android123提示遊戲開發者,這點比較有意思的是Google 推出NDK可能是幫助遊戲開發人員,比如OpenGL ES的支援有明顯的改觀,原生代碼操作圖形介面是很必要的。


●  圖形物件優化,這裡要說的是Android上的Bitmap物件銷燬,可以藉助recycle()方法顯示讓GC回收一個Bitmap物件,通常對一個不用的Bitmap可以使用下面的方式,如


if(bitmapObject.isRecycled()==false) //如果沒有回收  
         bitmapObject.recycle();   


●  目前系統對動畫支援比較弱智對於常規應用的補間過渡效果可以,但是對於遊戲而言一般的美工可能習慣了GIF方式的統一處理,目前Android系統僅能預覽GIF的第一幀,可以藉助J2ME中通過執行緒和自己寫解析器的方式來讀取GIF89格式的資源。


● 對於大多數Android手機沒有過多的物理按鍵可能我們需要想象下了做好手勢識別 GestureDetector 和重力感應來實現操控。通常我們還要考慮誤操作問題的降噪處理。


Android堆記憶體也可自己定義大小


   對於一些大型Android專案或遊戲來說在演算法處理上沒有問題外,影響效能瓶頸的主要是Android自己記憶體管理機制問題,目前手機廠商對RAM都比 較吝嗇,對於軟體的流暢性來說RAM對效能的影響十分敏感,除了上次Android開發網提到的 優化Dalvik虛擬機器的堆記憶體分配外,我們還可以強制定義自己軟體的對記憶體大小,我們使用Dalvik提供的 dalvik.system.VMRuntime類來設定最小堆記憶體為例:


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


VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //設定最小heap記憶體為6MB大小。當然對於記憶體吃緊來說還可以通過手動干涉GC去處理,我們將在下次提到具體應用。


優化Dalvik虛擬機器的堆記憶體分配


對 於Android平臺來說,其託管層使用的Dalvik JavaVM從目前的表現來看還有很多地方可以優化處理,比如我們在開發一些大型遊戲或耗資源的應用中可能考慮手動干涉GC處理,使用 dalvik.system.VMRuntime類提供的setTargetHeapUtilization方法可以增強程式堆記憶體的處理效率。當然具體 原理我們可以參考開源工程,這裡我們僅說下使用方法:   private final static floatTARGET_HEAP_UTILIZATION = 0.75f; 在程式onCreate時就可以呼叫 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。
 
 
介紹一下圖片佔用程序的記憶體演算法吧。
android中處理圖片的基礎類是Bitmap,顧名思義,就是點陣圖。佔用記憶體的演算法如下:
圖片的width*height*Config。
如果Config設定為ARGB_8888,那麼上面的Config就是4。一張480*320的圖片佔用的記憶體就是480*320*4 byte。
前面有人說了一下8M的概念,其實是在預設情況下android程序的記憶體佔用量為16M,因為Bitmap他除了java中持有資料外,底層C++的 skia圖形庫還會持有一個SKBitmap物件,因此一般圖片佔用記憶體推薦大小應該不超過8M。這個可以調整,編譯原始碼時可以設定引數。

相關推薦

Android DEX方法超過64K和gradle編譯OOM解決方案

首先貼上報錯資訊:Error:Execution failed for task ':app:transformClassesWithDexForDebug'.> com.android.build.api.transform.TransformException:

Eclipse版本android 65535解決方案(原理等同android studio現在的分包方式)(轉)

由於工作的需要看了下Eclipse下android65535的解決方案,查了好多文件,真心的發自內心的說一句請不要再拷貝別人的部落格了,害人,真害人。   接下來我說下我的實現方式,首先說下65535的最可能的觸發原因(三方jar用的太多了)   首先:利用ant 軟體合併jar包:

Android thread_local解決方案

thread_local Android解決方案 背景:Android的run time不支援thread local storage(TLS),其實是沒有實現,Android的run time沒有用gnu 的glibc,而是使用Google自己實現的Bionic,很多功能沒有實現,留了

android解決方案--用BroadcastReceiver監聽手機網路狀態變化

實現一個功能,可以有很多種方法,但我們所追求的是最適合於自己專案的那一種方法。 就比如app要判斷網路狀態,如果在每次使用網路的時候去判斷一次網路狀態的話,有些耗費時間。例如,你要在開啟網頁之前先判斷網路是否暢通以及在下載圖片之前判斷網路型別,那麼務必造成等待時間的增加

AndroidStudio 使用技巧:無法刪除 Android Emulator 解決方案

如果你刪除 Android Emulator 提示 The selected AVD is currently running in the Emulator !那麼你可以繼續看下去! 處理方法還是蠻簡單, Stackoverflow 已經給出解決方法 In Linux

Java常見記憶體溢位(OOM)解決方案

1,         程式計數器 一塊很小的記憶體空間,作用是當前執行緒所執行的位元組碼的行號指示器。 2,         java棧 與程式計數器一樣,java棧(虛擬機器棧)也是執行緒私有的,其生命週期與執行緒相同。通常存放基本資料型別,物件引用(一個指向物件起始地址

Unable to load script from assets 'index.android.bundle'.解決方案

剛接觸React Native,新建了一個專案,在Android Studio的模擬器上可以執行,但用Genymotion模擬器執行時卻報如下錯誤: 上網查了一下,很多文章都提出下面的解決方法: 1.首先手動在android/app/src/main目錄下建立一個as

Android_效能優化之ViewPager載入成百上千高清大圖oom解決方案

歡迎加入技術談論群:714476794一、背景最近做專案需要用到選擇圖片上傳,類似於微信、微博那樣的圖片選擇器,ContentResolver讀取本地圖片資源並用RecyclerView+Glide載入圖片顯示就搞定列表的顯示,這個沒什麼大問題,重點是,點選圖片進入大圖瀏覽,

oom解決方案

容易 proc 永久 lin linu 範圍 狀態 足夠 follow 1)由於進程的虛擬地址空間比物理內存大很多, linux還提供了一系列的機制, 來應對內存不足的情況 回收緩存: 使用LRU 算法, 回收最近使用最少的內存頁面 回收不常訪問的內存, 把

Android高效載入大圖、多圖解決方案,有效避免程式OOM

本篇文章主要內容來自於Android Doc,我翻譯之後又做了些加工,英文好的朋友也可以直接去讀原文。高效載入大圖片我們在編寫Android程式的時候經常要用到許多圖片,不同圖片總是會有不同的形狀、不同的大小,但在大多數情況下,這些圖片都會大於我們程式所需要的大小。比如說系統

關於android 使用bitmap的OOM心得和解決方案

android開發,從2010年開始學習到現在的獨立完成一個app,這漫長的四年,已經經歷了很多次bug的折磨,無數次的加班訓練。然而,自以為自己已經比較瞭解android了,卻最近在一個專案上,因為oom而折騰了一個周,回到原地,認識了自己的不足,感覺自己是如此的菜鳥呀。

Android OOM解決方案

儘量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource來設定一張大圖, 因為這些函式在完成decode後,最終都是通過java層的createBitmap來完成的,需要消耗更多記憶體。 因此,改用

Android高效載入大圖、多圖解決方案,有效避免程式OOM .

高效載入大圖片 我們在編寫Android程式的時候經常要用到許多圖片,不同圖片總是會有不同的形狀、不同的大小,但在大多數情況下,這些圖片都會大於我們程式所需要的大小。比如說系統圖片庫裡展示的圖片大都是用手機攝像頭拍出來的,這些圖片的解析度會比我們手機螢幕的解析度高得多。大家應該知道,我們編寫的應用程式都

Android高效加載大圖、多圖解決方案,有效避免程序OOM

view idv alc ash ces cal android手機 ons 多圖 前言:Android手機分配給給個應用的內存空間都是有限的,當圖片像素>屏幕像素時,會造成內存浪費,嚴重時更會造成oom,當圖片像素<屏幕像素時,又會導致展示出來的圖片失真,因此

Android記憶體洩漏解決方案(OOM)

為什麼會有記憶體洩漏? 一個不會被使用的物件,因為另一個正在使用的物件持有該物件的引用,導致它不能正常被回收,而停留在堆記憶體中,記憶體洩漏就產生了 Android系統為每個應用分配的記憶體是有限的,記憶體洩漏會使我們的應用記憶體隨著時間不斷的增加,造成應用

Android 記憶體溢位解決方案OOM) 整理總結

在最近做的工程中發現載入的圖片太多或圖片過大時經常出現OOM問題,找網上資料也提供了很多方法,但自己感覺有點亂,特此,今天在不同型號的三款安卓手機上做了測試,因為有效果也有結果,今天小馬就做個詳細的總結,以供朋友們共同交流學習,也供自己以後在解決OOM問題上有所提高,提前講下,片幅有點長,涉及的東西太

Android記憶體溢位解決方案OOM

眾所周知,每個Android應用程式在執行時都有一定的記憶體限制,限制大小一般為16MB或24MB(視平臺而定)。因此在開發應用時需要特別關注自身的記憶體使用量,而一般最耗記憶體量的資源,一般是圖片、音訊檔案、視訊檔案等多媒體資源;由於Android系統對音訊、視訊等資源做了邊解析便播放的處理,使用時並不

Android 面試題 關於oom解決方案

#Android關於OOM的解決方案 ##OOM 記憶體溢位(Out Of Memory)也就是說記憶體佔有量超過了VM所分配的最大 ##出現OOM的原因 載入物件過大相應資源過多,來不及釋放 ##

Android關於OOM解決方案

在Android平臺上面,應用程式OOM異常永遠都是值得關注的問題。通常這一塊也是程式這中的重點之一。這下我就如何解決OOM作一點簡單的介紹。     首先,OOM就是記憶體溢位,即Out Of

Android studio 代碼突然報錯解決方案

cache dst roi image 技術分享 users 方案 file sdn 1.點擊File->Invalidate Caches / Restart... 2.重啟Gradle,清除緩存 3.Clean Project 4.關閉Android Stud