android 用GridView載入Bitmap 記憶體溢位問題總結
1) 要及時回收Bitmap的記憶體
Bitmap類有一個方法recycle(),從方法名可以看出意思是回收。這裡就有疑問了,Android系統有自己的垃圾回收機制,可以不定期的回收掉不使用的記憶體空間,當然也包括Bitmap的空間。那為什麼還需要這個方法呢?
Bitmap類的構造方法都是私有的,所以開發者不能直接new出一個Bitmap物件,只能通過BitmapFactory類的各種靜態方法來例項化一個Bitmap。仔細檢視BitmapFactory的原始碼可以看到,生成Bitmap物件最終都是通過JNI呼叫方式實現的。所以,載入Bitmap到記憶體裡以後,是包含兩部分記憶體區域的。簡單的說,一部分是
那如果不呼叫recycle(),是否就一定存在記憶體洩露呢?也不是的。Android的每個應用都執行在獨立的程序裡,有著獨立的記憶體,如果整個程序被應用本身或者系統殺死了,記憶體也就都被釋放掉了,當然也包括C部分的記憶體。
Android對於程序的管理是非常複雜的。簡單的說,Android系統的程序分為幾個級別,系統會在記憶體不足的情況下殺死一些低優先順序的程序,以提供給其它程序充足的記憶體空間。在實際專案開發過程中,有的開發者會在退出程式的時候使用Process.killProcess(Process.myPid())的方式將自己的程序殺死,但是有的應用僅僅會使用呼叫Activity.finish()方法的方式關閉掉所有的Activity。
經驗分享:
Android手機的使用者,根據習慣不同,可能會有兩種方式退出整個應用程式:一種是按Home鍵直接退到桌面;另一種是從應用程式的退出按鈕或者按Back鍵退出程式。那麼從系統的角度來說,這兩種方式有什麼區別呢?按Home鍵,應用程式並沒有被關閉,而是成為了後臺應用程式。按Back鍵,一般來說,應用程式關閉了,但是程序並沒有被殺死,而是成為了空程序(程式本身對退出做了特殊處理的不考慮在內)。
Android系統已經做了大量程序管理的工作,這些已經可以滿足使用者的需求。個人建議,應用程式在退出應用的時候不需要手動殺死自己所在的程序。對於應用程式本身的程序管理,交給Android系統來處理就可以了。應用程式需要做的,是儘量做好程式本身的記憶體管理工作。
一般來說,如果能夠獲得Bitmap物件的引用,就需要及時的呼叫Bitmap的recycle()方法來釋放Bitmap佔用的記憶體空間,而不要等Android系統來進行釋放。
下面是釋放Bitmap的示例程式碼片段。
// 先判斷是否已經回收
if(bitmap != null && !bitmap.isRecycled()){
// 回收並且置為null
bitmap.recycle();
bitmap = null;
}
System.gc();
從上面的程式碼可以看到,bitmap.recycle()方法用於回收該Bitmap所佔用的記憶體,接著將bitmap置空,最後使用System.gc()呼叫一下系統的垃圾回收器進行回收,可以通知垃圾回收器儘快進行回收。這裡需要注意的是,呼叫System.gc()並不能保證立即開始進行回收過程,而只是為了加快回收的到來。
如何呼叫recycle()方法進行回收已經瞭解了,那什麼時候釋放Bitmap的記憶體比較合適呢?一般來說,如果程式碼已經不再需要使用Bitmap物件了,就可以釋放了。釋放記憶體以後,就不能再使用該Bitmap物件了,如果再次使用,就會丟擲異常。所以一定要保證不再使用的時候釋放。比如,如果是在某個Activity中使用Bitmap,就可以在Activity的onStop()或者onDestroy()方法中進行回收。
2) 捕獲異常
因為Bitmap是吃記憶體大戶,為了避免應用在分配Bitmap記憶體的時候出現OutOfMemory異常以後Crash掉,需要特別注意例項化Bitmap部分的程式碼。通常,在例項化Bitmap的程式碼中,一定要對OutOfMemory異常進行捕獲。
以下是程式碼示例。
Bitmap bitmap = null;
try {
// 例項化Bitmap
bitmap = BitmapFactory.decodeFile(path);
} catch (OutOfMemoryError e) {
//
}
if (bitmap == null) {
// 如果例項化失敗 返回預設的Bitmap物件
return defaultBitmapMap;
}
這裡對初始化Bitmap物件過程中可能發生的OutOfMemory異常進行了捕獲。如果發生了OutOfMemory異常,應用不會崩潰,而是得到了一個預設的Bitmap圖。
經驗分享:
很多開發者會習慣性的在程式碼中直接捕獲Exception。但是對於OutOfMemoryError來說,這樣做是捕獲不到的。因為OutOfMemoryError是一種Error,而不是Exception。在此僅僅做一下提醒,避免寫錯程式碼而捕獲不到OutOfMemoryError。
3) 快取通用的Bitmap物件
有時候,可能需要在一個Activity裡多次用到同一張圖片。比如一個Activity會展示一些使用者的頭像列表,而如果使用者沒有設定頭像的話,則會顯示一個預設頭像,而這個頭像是位於應用程式本身的資原始檔中的。
如果有類似上面的場景,就可以對同一Bitmap進行快取。如果不進行快取,儘管看到的是同一張圖片檔案,但是使用BitmapFactory類的方法來例項化出來的Bitmap,是不同的Bitmap物件。快取可以避免新建多個Bitmap物件,避免記憶體的浪費。
經驗分享:
Web開發者對於快取技術是很熟悉的。其實在Android應用開發過程中,也會經常使用快取的技術。這裡所說的快取有兩個級別,一個是硬碟快取,一個是記憶體快取。比如說,在開發網路應用過程中,可以將一些從網路上獲取的資料儲存到SD卡中,下次直接從SD卡讀取,而不從網路中讀取,從而節省網路流量。這種方式就是硬碟快取。再比如,應用程式經常會使用同一物件,也可以放到記憶體中快取起來,需要的時候直接從記憶體中讀取。這種方式就是記憶體快取。
4) 壓縮圖片
如果圖片畫素過大,使用BitmapFactory類的方法例項化Bitmap的過程中,需要大於8M的記憶體空間,就必定會發生OutOfMemory異常。這個時候該如何處理呢?如果有這種情況,則可以將圖片縮小,以減少載入圖片過程中的記憶體的使用,避免異常發生。
使用BitmapFactory.Options設定inSampleSize就可以縮小圖片。屬性值inSampleSize表示縮圖大小為原始圖片大小的幾分之一。即如果這個值為2,則取出的縮圖的寬和高都是原始圖片的1/2,圖片的大小就為原始大小的1/4。
如果知道圖片的畫素過大,就可以對其進行縮小。那麼如何才知道圖片過大呢?
使用BitmapFactory.Options設定inJustDecodeBounds為true後,再使用decodeFile()等方法,並不會真正的分配空間,即解碼出來的Bitmap為null,但是可計算出原始圖片的寬度和高度,即options.outWidth和options.outHeight。通過這兩個值,就可以知道圖片是否過大了。
BitmapFactory.Options opts = new BitmapFactory.Options();
// 設定inJustDecodeBounds為true
opts.inJustDecodeBounds = true;
// 使用decodeFile方法得到圖片的寬和高
BitmapFactory.decodeFile(path, opts);
// 打印出圖片的寬和高
Log.d("example", opts.outWidth + "," + opts.outHeight);
在實際專案中,可以利用上面的程式碼,先獲取圖片真實的寬度和高度,然後判斷是否需要跑縮小。如果不需要縮小,設定inSampleSize的值為1。如果需要縮小,則動態計算並設定inSampleSize的值,對圖片進行縮小。需要注意的是,在下次使用BitmapFactory的decodeFile()等方法例項化Bitmap物件前,別忘記將opts.inJustDecodeBound設定回false。否則獲取的bitmap物件還是null。
經驗分享:
如果程式的圖片的來源都是程式包中的資源,或者是自己伺服器上的圖片,圖片的大小是開發者可以調整的,那麼一般來說,就只需要注意使用的圖片不要過大,並且注意程式碼的質量,及時回收Bitmap物件,就能避免OutOfMemory異常的發生。
如果程式的圖片來自外界,這個時候就特別需要注意OutOfMemory的發生。一個是如果載入的圖片比較大,就需要先縮小;另一個是一定要捕獲異常,避免程式Crash。
相關推薦
android 用GridView載入Bitmap 記憶體溢位問題總結
總結二: 1) 要及時回收Bitmap的記憶體 Bitmap類有一個方法recycle(),從方法名可以看出意思是回收。這裡就有疑問了,Android系統有自己的垃圾回收機制,可以不定期的回收掉不使用的記憶體空間,當然也包括Bitmap的空間。那為什麼還需要這個方法呢? Bitmap類的構造方法都是私有的,
Android從伺服器取圖片向Bitmap載入時記憶體溢位問題
最近暑假在做一個APP專案,需要從伺服器取圖片。 突然就顯示 BitmapFactory.decodeStream java.lang.OutOfMemoryError 意思是記憶體溢位了,在網上搜索後已解決。現在將查到的解決方法進行整理一下,方便下次遇到時可以使用。 首先顯
android檔案快取及SD卡建立資料夾失敗解決和bitmap記憶體溢位解決
1.相關程式碼: 新增許可權: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:na
android 本地大圖片造成記憶體溢位的解決方案
在使用中,小的圖片,可以通過drawable直接引用setImageResource或者setBackgroundResource, 但涉及到大圖時,儘量通過decodeStream來建立bitmap,然後再給對應的view使用。 public static Bitmap readBitMap(
Android利用GridView載入九宮格選單
效果圖如下:第一步:佈局main.xml檔案,這裡使用了一個GridView和一個滾動文字控制元件<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schem
Android用GridView畫帶背景色和點選事件的簡單表格
一:效果圖 六步即可完成GridView不同背景色,並且每個單元格可點選 GridView佈局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="h
Android 中關於載入Bitmap知識點
在安卓開發中遇到載入圖片是很平常的事情,圖片即bitmap,但是Android對於每一個應用程式只分配了16M的記憶體空間,所以在載入比較大點的bitmap的時候很容易,會出現OOM異常。 android 中載入圖片的類BitmapFactary,提供了四類方法:decodeS
android用webview載入H5頁面出現點選事件失效的問題解決
不論點選還是標籤連結都失效,反覆查閱,可能性方法試了又試最終解決。總結下:1.開啟js支援2.webview 設定WebChromeClient3.websetting和webviewclientimport android.os.Bundle; import androi
Android下的,OOM記憶體溢位解決方法\AsyncTask
在Android平臺上面,應用程式OOM異常永遠都是值得關注的問題。通常這一塊也是程式這中的重點之一。這下我就如何解決OOM作一點簡單的介紹。 首先,OOM就是記憶體溢位,即Out Of Memory。也就是說記憶體佔有量超過了VM所分配的最大。 怎麼解決
Android(decode檔案轉成bitmap)使用BitmapFactory.Options解決載入大圖片記憶體溢位
由於Android對圖片使用記憶體有限制,若是載入幾兆的大圖片便記憶體溢位。Bitmap會將圖片的所有畫素(即長x寬)載入到記憶體中,如果圖片解析度過大,會直接導致記憶體溢位(java.lang.OutOfMemoryError),只有在BitmapFactory載入
android載入大量圖片記憶體溢位的三種解決辦法
方法一: 在從網路或本地載入圖片的時候,只加載縮圖。 /** * 按照路徑載入圖片 * @param path 圖片資源的存放路徑 * @param scalSize 縮小的倍數 * @return */ public s
Android--圖片載入處理(記憶體溢位和三級快取)
最簡單的解決辦法,用現成的框架,推薦glide和picasso用法:在build.gradle中加入:repositories { mavenCentral() maven { url 'https://maven.google.com' } } dependenc
Android避免記憶體溢位(Out of Memory)方法總結
避免記憶體溢位的方法,主要是對以下三個方面對程式進行優化 記憶體引用 在處理記憶體引用之前,我們先來複習下什麼是強引用、軟引用、弱引用、虛引用 強引用:強引用是使用最普遍的引用。如果一個物件具有強引用,那垃圾回收器絕不會回收它。 當記憶體空間不足,Java虛擬機器寧願丟擲O
Android利用縮放載入大圖片避免記憶體溢位
因為安卓的堆記憶體有限(儘管現在隨著安卓手機螢幕解析度的提高堆記憶體沒有以前小螢幕時代那麼侷限),要是完全載入一張大圖片很容易導致OOM(out of memory)的問題。 所以為了解決這一情況,我
Android 載入圖片過程導致記憶體溢位(Out Of Memory)
載入圖片的時候,啪啪啪就OOM了。 解決圖片OOM之前,先來了解一下一張圖片記憶體佔用的相關因素——圖片質量,圖片尺寸,填充區域 圖片質量 質量就是圖片大小(多少MB,多少KB)。相對情況下圖片越大,佔用記憶體越大 圖片尺寸 圖片尺寸=圖片的寬高,
Android Bitmap圖片處理,防止記憶體溢位
在android 中載入一張圖片,如果圖片過大就有可能會出現記憶體溢位,特別是在載入資料過多的時候,像ListView 和GridView等重複列表中,因此在處理Android圖片防止記憶體溢位就顯得特別的重要,也是很多面試中經常問到的問題,面試官通常都會讓你談
Android 記憶體溢位解決方案(OOM) 整理總結
在最近做的工程中發現載入的圖片太多或圖片過大時經常出現OOM問題,找網上資料也提供了很多方法,但自己感覺有點亂,特此,今天在不同型號的三款安卓手機上做了測試,因為有效果也有結果,今天小馬就做個詳細的總結,以供朋友們共同交流學習,也供自己以後在解決OOM問題上有所提高,提前講下,片幅有點長,涉及的東西太
android--使用Canvas,Bitmap出現OOM-記憶體溢位
public class MyView { private Canvas mCanvas; private Bitmap mBitmap; private static Bitmap mFreeBitmap; static { mFree
Android載入圖片出現記憶體溢位的解決
一、儘量使用BitmapFactory.decodeStream BitmapFactory.decodeResource來設定圖片資源要消耗更多的記憶體,如果程式中的圖片資源很多的話,那這個記憶體就很客觀啦。主要因為是 BitmapFactory.decodeReso
Android--Gridview使用SimpleAdapter載入bitmap圖片
在給Gridview設定Item的時候,需要填充圖片和文字兩個Item,若是採用SimpleAdapter來載入Gridview的話,直接傳入本地的圖片資源ID是可以正常顯示的。但是如果要顯示bitmap資源的話,則需要在set之前通過setViewBinder這個介面轉換