一、將圖片轉化爲縮略圖再加載: java
1 BitmapFactory.Options options = new BitmapFactory.Options(); 2 options.inSampleSize = 2; 3 Bitmap img = BitmapFactory.decodeFile("/sdcard/1.png", options);
該段代碼即是讀取1.png的縮略圖,長度、寬度都只有原圖片的1/2。圖片大小削減,佔用的內存自然也變小了。這麼作的弊病是圖片質量變差,inSampleSize的值越大,圖片的質量就越差。由於各手機廠商縮放圖片的算法不合,在不合手機上的縮放圖片質量可能會不合。筆者就遭受過moto手機上圖片縮放後質量能夠接管,三星手機上一樣的縮放比例,質量卻差不少的景象。 算法
二、用ARBG_4444色彩模式加載圖片: 數組
Android中有四種,分別是: 函數
ALPHA_8:每一個像素佔用1byte內存 post
ARGB_4444:每一個像素佔用2byte內存 優化
ARGB_8888:每一個像素佔用4byte內存 spa
RGB_565:每一個像素佔用2byte內存 線程
Android默認的色彩模式爲ARGB_8888,這個色彩模式色彩最細膩,顯示質量最高。但一樣的,佔用的內存也最大。 code
1 BitmapFactory.Options options = new BitmapFactory.Options(); 2 options.inPreferredConfig = Bitmap.Config.ARGB_4444; 3 Bitmap img = BitmapFactory.decodeFile("/sdcard/1.png", options);
以上代碼即是將1.png以ARGB_4444模式讀出。內存削減當然不如第一種辦法明顯,然則對於大多半圖片,看不出與ARGB_8888模式有什麼差異。不過在讀取有漸變結果的圖片時,可能有色彩條呈現。別的,會影響圖片的殊效處理懲罰。 對象
三、調用圖片的recycle()辦法:
這個其實不是真正降落圖片內存的辦法。首要目標是標識表記標幟圖片對象,便利收受接管圖片對象的本地數據。圖片對象的本地數據佔用的內存最大,而且與法度Java項目組的內存是分隔策畫的。因此常常呈現Java heap足夠應用,而圖片產生OutOfMemoryError的景象。在圖片不該用時調用該辦法,能夠有效降落圖片本地數據的峯值,從而削減OutOfMemoryError的機率。不過調用了recycle()的圖片對象處於「放棄」情況,調用時會形成法度錯誤。因此在沒法包管該圖片對象絕對不會被再次調用的景象下,不建議應用該辦法。希罕要重視已經用setImageBitmap(Bitmap img)辦法分派給控件的圖片對象,可能會被體系類庫調用,形成法度錯誤。
四、應用Matrix對象放大的圖片如何更改色彩模式:
當然應用Matrix對象放大圖片,必然會花費更多的內存,但有時辰也不得不如許作。放大後的圖片應用的ARGB_8888色彩模式,就算原圖片是ARGB_4444色彩模式也同樣,而且沒有辦法在放大時直接指定色彩模式。能夠採起如下辦法更改圖片色彩模式。
Matrix matrix = new Matrix(); float newWidth = 200;//圖片放大後的寬度 float newHeight = 300;//圖片放大後的長度 matrix.postScale(newWidth / img.getWidth(), newHeight/ img.getHeight()); Bitmap img1 = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);//得到放大的圖片 img2 = img1.copy(Bitmap.Config.ARGB_4444, false);//得到ARGB_4444色彩模式的圖片 img = null; img1 = null;
這裏比起原本的圖片額外生成了一個圖片對象img1。然則體系會主動收受接管img1,因此實際內存仍是削減了。
歸結起來仍是以縮略圖模式讀取圖片和削減圖片中每一個像素佔用的內存。這兩種辦法當然有效,然則也有各自的弊病。實際開闢中仍是應當按照景象酌情應用。最王道的辦法,仍是避免垃圾對象的產生。例如在ListView的應用中,複用convertView等。如果應用AsyncTask加載圖片,要及時將引用的ImageView對象置爲null。由於AsyncTask是用線程池實現的,因此此中引用的對象可能會擁有很長的生命週期,形成GC沒法開釋。我仍是信賴Android的內存收受接管機制的,recycle什麼的當然必然程度上有效,但總感受不合適Java內存收受接管的原則。(最後這句美盡是着魔了)
補充...
儘可能不要使用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中配置相應的圖片資源,
不然在不一樣分辨率機器上都是一樣大小(像素點數量),顯示出來的大小就不對了.
BitmapFactory.Options.inPreferredConfig
ALPHA_8:數字爲8,圖形參數應該由一個字節來表示,應該是一種8位的位圖
ARGB_4444:4+4+4+4=16,圖形的參數應該由兩個字節來表示,應該是一種16位的位圖.
ARGB_8888:8+8+8+8=32,圖形的參數應該由四個字節來表示,應該是一種32位的位圖.
RGB_565:5+6+5=16,圖形的參數應該由兩個字節來表示,應該是一種16位的位圖.
ALPHA_8,ARGB_4444,ARGB_8888都是透明的位圖,也就是所字母A表明透明.
ARGB_4444:意味着有四個參數,即A,R,G,B,每個參數由4bit表示.
ARGB_8888:意味着有四個參數,即A,R,G,B,每個參數由8bit來表示.
RGB_565:意味着有三個參數,R,G,B,三個參數分別佔5bit,6bit,5bit.
BitmapFactory.Options.inPurgeable;
若是 inPurgeable 設爲True的話表示使用BitmapFactory建立的Bitmap
用於存儲Pixel的內存空間在系統內存不足時能夠被回收,
在應用須要再次訪問Bitmap的Pixel時(如繪製Bitmap或是調用getPixel),
系統會再次調用BitmapFactory decoder從新生成Bitmap的Pixel數組.
爲了可以從新解碼圖像,bitmap要可以訪問存儲Bitmap的原始數據.
在inPurgeable爲false時表示建立的Bitmap的Pixel內存空間不能被回收,
這樣BitmapFactory在不停decodeByteArray建立新的Bitmap對象,
不一樣設備的內存不一樣,所以可以同時建立的Bitmap個數可能有所不一樣,
200個bitmap足以使大部分的設備從新OutOfMemory錯誤.
當isPurgable設爲true時,系統中內存不足時,
能夠回收部分Bitmap佔據的內存空間,這時通常不會出現OutOfMemory 錯誤.