Android 關於OOM的解決方案

2021-06-10 02:27:58 字數 2522 閱讀 2473

在android平台上面,應用程式oom異常永遠都是值得關注的問題。通常這一塊也是程式這中的重點之一。這下我就如何解決oom作一點簡單的介紹。

首先,oom就是記憶體溢位,即out of memory。也就是說記憶體占有量超過了vm所分配的最大。

怎麼解決oom,通常oom都發生在需要用到大量記憶體的情況下(建立或解析bitmap,分配特大的陣列等),在這樣的一種情況下,就可能出現oom,據我現在了解到,多數oom都是因為bitmap太大。所以,這裡我就專門針對如何解決bitmap的oom。其實最核發的就是只載入可見範圍內的bitmap,試想這樣一種情況,在gridview或listview中,資料量有5000,每一屏只顯示20個元素,那麼不可見的,我們是不需要儲存bitmap在內在中的。所以我們就是只把那麼可見的bitmap保留在記憶體中,那些不可見的,就釋放掉。當元素滑出來時,再去載入bitmap。

這裡我有兩種方式,都可以避免oom。

這種方式我簡單說一下,不太推薦,這也是我最開始使用的一種方法,但最後證明它不是最好的。(不推薦)

1、只載入可見區域的bitmap

2、滑動時不載入

4、釋放滑出可見區域的bitmap的內在。

1、我們需要監聽gridview/listview的滑動事件,這個很簡單做到,abslistview#setonscrolllistener(onscrolllistener l)

2、主動呼叫bitmap#recycle()方法,它會導致乙個問題,必須判斷這個bitmap是否被乙個view(imageview等)所引用,如果被引用,我們不能簡單地呼叫recycle()方法,這樣會導致異常,說是view使用了乙個已經被**的bitmap。

3,我們必須設計自己的執行緒來控制開始/暫停等,因為gridview/listview的滑動狀態可能不斷地變化,也就是說滑動->停止->滑動,這種狀態可能不斷變化,這樣就會導致我們的執行緒中的run()方法裡面的邏輯比較複雜,一旦複雜,問題就可能就得更多。

基於以上幾點,這種方式不是最好的,所以不推薦。

這種方式,我覺得是比較好的一種,它首先利用了cache,我認為cache是乙個很重要的東西,把bitmap的記憶體單獨放在乙個地方來管理,這個地方就是cache,它的容量是一定的,我們可能會不斷的向這個cache中新增元素,也可能不斷的移除元素。

為了更好的說明這種方式,先要介紹一下lrucache。

1、這其實就是乙個linkedhashmap,任意時刻,當乙個值被訪問時,它就會被移動到佇列的開始位置,所以這也是為什麼要用linkedhashmap的原因,因為要頻繁的做移動操作,為了提高效能,所以要用linkedhashmap。當cache滿了時,此時再向cache裡面新增乙個值,那麼,在佇列最後的值就會從佇列裡面移除,這個值就有可能被gc**掉。

2、如果我們想主動釋放記憶體,也是可以的,我們可以重寫entryremoved(boolean, k, v, v)方法。

3、這個類是執行緒安全的,在多執行緒下面使用這個類,沒不會存在問題。

synchronized (cache) }

4、lrucache的apilevel是12,也就是說,我們在sdk 2.3.x以下是無法使用的,但是沒關係,lrucache的原始碼不算複雜,我們可以直接把它拷貝到自己的工程目錄就可以了。

這個類也是乙個很重要也很常用的類。它封裝了thread和handler,我們使用就更加方便,不用關注handler,我們知道,在後台執行緒中是不能更新ui,而很多情況下,我們在後台執行緒做完一件事情後,一般都會更新ui,一般的做法是向關聯到ui執行緒的handler傳送乙個message,在handler裡面去處理這個message,從而更新ui。用了asynctask之後,我們就不用關注handler了。這個類有幾個重要的方法:

1、onpreexecute(): 在ui執行緒裡面呼叫,它在這個task執行後會立即呼叫。我們在這個方法裡面通常是用於建立乙個任務,比如顯示乙個等待對話方塊來通知使用者。

3、onprogressupdate(progress...):執行在ui執行緒,在呼叫publishprogress()方法之後。這個方法用來在ui上顯示任何形式的進度,比如你可以顯示乙個等待對話方塊,也可以顯示乙個文字形式的log,還可以顯示toast對話方塊。

4、onpostexecute(result):當task結束後呼叫,它執行在ui執行緒。

5、取消乙個task,我們可以在任何時候呼叫cancel(boolean)來取消乙個任務,當呼叫了cancel()方法後,oncancelled(object)方法就會被呼叫,onpostexecute(object)方法不會被呼叫,在doinbackground(object)方法中,我們可以用iscancelled()方法來檢查任務是否取消。

6、幾點規則

1、始終從cache中去取bitmap,如果取到bitmap,就直接把這個bitmap設定到imageview上面。

2、如果快取中不存在,那麼啟動乙個task去載入(可能從檔案來,也可能從網路)。

3、每乙個imageview上面都可能繫結乙個task,所以,這個imageview必須提供乙個方法能得到與之相關聯的task,為什麼要這樣做?因為在給乙個imageview繫結task之前,必須要把原先的task取消。

Android 優化Bitmap避免OOM

使用android提供的bitmapfactory解碼時,往往會因為過大而遇到 outofmemoryerror的異常。要想正常使用,一種簡便的方式是分配更少的記憶體空間來儲存,即在載入的時候以犧牲質量為代價,將進行放縮,這是一種避免oom所採用的解決方法。但是,這種方法是得不償失的,犧牲了質量。在...

什麼是oom,常見造成oom的原因,及解決方法

一 什麼是oom oom就是我們常說的記憶體溢位,它是指需要的記憶體空間大於系統分配的記憶體空間,oom後果就是專案程式crash 二 常見造成oom的原因 1.記憶體洩露造成 2.載入的檔案或者過大造成 三 解決方案 記憶體洩露是造成記憶體溢位的乙個原因,所以避免記憶體洩露的那些方法都適用於記憶體...

oom問題解決

dalvik虛擬機會為應用程式分配固定大小的heap 如果使用超過了這個heap的大小,且沒有可被 物件,就會報oom。多張較大會迅速占用空間造成oom。我們可以使用一下的方法來減少這種情況的產生 1.減少單張的大小,根據螢幕大小來對bitmap做resize。private void setima...