Admin 2012年6月24日 名人名言:時間就是
1、將圖片轉化為縮略圖再加載:
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手機上圖片縮放后質量可以接管,三星手機上同樣的縮放比例,質量卻差很多的景象。
2、用ARBG_4444色彩模式加載圖片:
Android中有四種,分別是:
ALPHA_8:每個像素占用1byte內存
ARGB_4444:每個像素占用2byte內存
ARGB_8888:每個像素占用4byte內存
RGB_565:每個像素占用2byte內存
Android默認的色彩模式為ARGB_8888,這個色彩模式色彩最細膩,顯示質量最高。但同樣的,占用的內存也最大。
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模式有什么差別。不過在讀取有漸變結果的圖片時,可能有色彩條呈現。別的,會影響圖片的殊效處理懲罰。
3、調用圖片的recycle()辦法:
這個其實不是真正降落圖片內存的辦法。首要目標是標識表記標幟圖片對象,便利收受接管圖片對象的本地數據。圖片對象的本地數據占用的內存最大,並且與法度Java項目組的內存是分隔策畫的。所以經常呈現Java heap足夠應用,而圖片產生OutOfMemoryError的景象。在圖片不應用時調用該辦法,可以有效降落圖片本地數據的峰值,從而削減OutOfMemoryError的概率。不過調用了recycle()的圖片對象處於“放棄”狀況,調用時會造成法度錯誤。所以在無法包管該圖片對象絕對不會被再次調用的景象下,不建議應用該辦法。希罕要重視已經用setImageBitmap(Bitmap img)辦法分派給控件的圖片對象,可能會被體系類庫調用,造成法度錯誤。
4、應用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 錯誤.