解決Android平臺中應用程序OOM異常的方法
在Android平臺上面,應用程序OOM異常永遠都是值得關注的問題。通常這一塊也是程序這中的重點之一。這下我就如何解決OOM作一點簡單的介紹。
首先,OOM就是內(nèi)存溢出,即Out Of Memory。也就是說內(nèi)存占有量超過了VM所分配的最大。
怎么解決OOM,通常OOM都發(fā)生在需要用到大量內(nèi)存的情況下(創(chuàng)建或解析Bitmap,分配特大的數(shù)組等),在這樣的一種情況下,就可能出現(xiàn)OOM,據(jù)我現(xiàn)在了解到,多數(shù)OOM都是因為Bitmap太大。所以,這里我就專門針對如何解決Bitmap的OOM。其實最核發(fā)的就是只加載可見范圍內(nèi)的Bitmap,試想這樣一種情況,在GridView或ListView中,數(shù)據(jù)量有5000,每一屏只顯示20個元素,那么不可見的,我們是不需要保存Bitmap在內(nèi)在中的。所以我們就是只把那么可見的Bitmap保留在內(nèi)存中,那些不可見的,就釋放掉。當元素滑出來時,再去加載Bitmap。
這里我有兩種方式,都可以避免OOM。
一、主動釋放Bitmap的內(nèi)存
這種方式我簡單說一下,不太推薦,這也是我最開始使用的一種方法,但最后證明它不是最好的。(不推薦)
它的本質(zhì)思路是:
1、只加載可見區(qū)域的Bitmap
2、滑動時不加載
3、停止滑動(Idle)后,開始重新加載可見區(qū)域的圖片
4、釋放滑出可見區(qū)域的Bitmap的內(nèi)在。
它比較復雜:
1、我們需要監(jiān)聽GridView/ListView的滑動事件,這個很簡單做到,AbsListView#setOnScrollListener(OnScrollListener l)
2、主動調(diào)用Bitmap#recycle()方法,它會導致一個問題,必須判斷這個Bitmap是否被一個View(ImageView等)所引用,如果被引用,我們不能簡單地調(diào)用recycle()方法,這樣會導致異常,說是View使用了一個已經(jīng)被回收的Bitmap。
3,我們必須設計自己的線程來控制開始/暫停等,因為GridView/ListView的滑動狀態(tài)可能不斷地變化,也就是說滑動->停止->滑動,這種狀態(tài)可能不斷變化,這樣就會導致我們的線程中的run()方法里面的邏輯比較復雜,一旦復雜,問題就可能就得更多。
基于以上幾點,這種方式不是最好的,所以不推薦。
二、設計Cache
這種方式,我覺得是比較好的一種,它首先利用了cache,我認為cache是一個很重要的東西,把Bitmap的內(nèi)存單獨放在一個地方來管理,這個地方就是cache,它的容量是一定的,我們可能會不斷的向這個cache中添加元素,也可能不斷的移除元素。
為了更好的說明這種方式,先要介紹一下LruCache。
LruCache
1、這其實就是一個LinkedHashMap,任意時刻,當一個值被訪問時,它就會被移動到隊列的開始位置,所以這也是為什么要用LinkedHashMap的原因,因為要頻繁的做移動操作,為了提高性能,所以要用LinkedHashMap。當cache滿了時,此時再向cache里面添加一個值,那么,在隊列最后的值就會從隊列里面移除,這個值就有可能被GC回收掉。
2、如果我們想主動釋放內(nèi)存,也是可以的,我們可以重寫entryRemoved(Boolean, K, V, V)方法。
3、這個類是線程安全的,在多線程下面使用這個類,沒不會存在問題。
synchronized (cache) {
if (cache.get(key) == null) {
cache.put(key, value);
}}
4、LruCache的APILevel是12,也就是說,我們在SDK 2.3.x以下是無法使用的,但是沒關系,LruCache的源碼不算復雜,我們可以直接把它拷貝到自己的工程目錄就可以了。
AsyncTask<>
這個類也是一個很重要也很常用的類。它封裝了Thread和Handler,我們使用就更加方便,不用關注Handler,我們知道,在后臺線程中是不能更新UI,而很多情況下,我們在后臺線程做完一件事情后,一般都會更新UI,一般的做法是向關聯(lián)到UI線程的Handler發(fā)送一個message,在Handler里面去處理這個message,從而更新UI。用了AsyncTask之后,我們就不用關注Handler了。這個類有幾個重要的方法:
1)、onPreExecute(): 在UI線程里面調(diào)用,它在這個task執(zhí)行后會立即調(diào)用。我們在這個方法里面通常是用于建立一個任務,比如顯示一個等待對話框來通知用戶。
2)、doInBackground(Params...):這個方法從名字就可以看出,它是運行在后臺線程的,在這個方法里面,去做耗時的事情,比如下載訪問網(wǎng)絡,操作文件等。這這個方法里面,我們可以調(diào)用publishProgress(Progress...)來調(diào)用當前任務的進度,調(diào)用了這個方法后,對應的onProgressUpdate(Progress...)方法會被調(diào)用,這個方法是運行在UI線程的。
3)、onProgressUpdate(Progress...):運行在UI線程,在調(diào)用publishProgress()方法之后。這個方法用來在UI上顯示任何形式的進度,比如你可以顯示一個等待對話框,也可以顯示一個文本形式的log,還可以顯示toast對話框。
4)、onPostExecute(Result):當task結束后調(diào)用,它運行在UI線程。
5)、取消一個task,我們可以在任何時候調(diào)用cancel(Boolean)來取消一個任務,當調(diào)用了cancel()方法后,onCancelled(Object)方法就會被調(diào)用,onPostExecute(Object)方法不會被調(diào)用,在doInBackground(Object[])方法中,我們可以用isCancelled()方法來檢查任務是否取消。
6)、幾點規(guī)則
AsyncTask實例必須在UI線程中創(chuàng)建
execute(Params...)方法必須在UI線程中調(diào)用。
不用手動調(diào)用onPreExecute(), onPostExecute(), doInBackground(), onProgressUpdate()方法。
一個任務只能被執(zhí)行一次。
總的思路
1、始終從cache中去取Bitmap,如果取到Bitmap,就直接把這個Bitmap設置到ImageView上面。
2、如果緩存中不存在,那么啟動一個task去加載(可能從文件來,也可能從網(wǎng)絡)。
3、每一個ImageView上面都可能綁定一個task,所以,這個ImageView必須提供一個方法能得到與之相關聯(lián)的task,為什么要這樣做?因為在給一個ImageView綁定task之前,必須要把原先的task取消。
以上就是解決應用程序OOM異常的方法,希望對大家的學習有所幫助。
相關文章
mac開發(fā)android環(huán)境搭建步驟圖解
這里比較詳細的來總結下mac開發(fā)android的環(huán)境搭建步驟安裝過程,希望對一些正準備配置Android開發(fā)環(huán)境的小伙伴們有一定幫助2014-01-01
android popuwindow點擊外部窗口不消失的實例
下面小編就為大家?guī)硪黄猘ndroid popuwindow點擊外部窗口不消失的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
android實現(xiàn)狀態(tài)欄添加圖標的函數(shù)實例
這篇文章主要介紹了android實現(xiàn)狀態(tài)欄添加圖標的函數(shù),較為詳細的分析了Android狀態(tài)欄添加及刪除圖標的具體實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10
Android Zxing 轉(zhuǎn)換豎屏掃描且提高識別率的方法
本篇文章主要介紹了Android Zxing 轉(zhuǎn)換豎屏掃描且提高識別率的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
Android 使用 okhttp3和retrofit2 進行單文件和多文件上傳
這篇文章主要介紹了Android 使用 okhttp3和retrofit2 進行單文件和多文件上傳,開發(fā)項目中需要進行單文件多文件的上傳功能,下面演示的ApiResponse是自己分裝的返回值,要根據(jù)自己的項目來完成,需要的朋友可以參考下2022-10-10
Android Studio 如何刪除/新建一個module(圖文教程詳解)
這篇文章主要介紹了Android Studio 如何刪除/新建一個module,此方法也會將該module從你的硬盤中刪除,如果直接右鍵會發(fā)現(xiàn)沒有delete選項,本文通過圖文并茂的形式給大家介紹的非常詳細,需要的朋友參考下吧2020-03-03
Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果示例
這篇文章主要介紹了Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果,涉及Android界面布局與屬性設置相關操作技巧,需要的朋友可以參考下2019-04-04
Android DaggerActivityComponent錯誤解決辦法詳解
這篇文章主要介紹了Android DaggerActivityComponent錯誤解決的相關資料,需要的朋友可以參考下2017-05-05
Intellij IDEA + Android SDK + Genymotion Emulator打造最佳Android
本文介紹Lorinnn在開發(fā)Android過程不斷跌打滾爬中安裝的一套開發(fā)環(huán)境,相信你在使用后同樣有不錯的體會。2014-07-07

