在作內存優化的時候,咱們發現除了解決內存泄露問題,剩下的就只有想辦法減小真實的內存佔用。而在App中,大部份內存可能被咱們圖片佔用了,因此減小圖片的內存佔用能夠帶來直接的效果。java
咱們先假設咱們有一張圖片是600 * 800像素的,圖片磁盤佔用空間大小假設是 100KB。android
圖片內存大小跟磁盤佔用空間大小有什麼關係?優化
磁盤佔用空間的大小不是圖片佔用內存的大小,磁盤佔用空間是在磁盤上存儲圖片須要的一個空間大小,內存大小是加載到內存中佔用的內存大小。兩個只是單位是同樣的,本質不是一個概念。編碼
一張圖片到底佔用多少內存呢?spa
圖片佔用內存的計算公式是:圖片高度 * 圖片寬度 * 一個像素佔用的內存大小,在Android中通常狀況下默認一個像素佔用內存是4個字節,因此上面的圖片佔用內存是:800 * 600 * 4 byte = 1875KB = 1.83M。爲何是4個字節呢?必定是4個字節麼?這兩個問題後面仔細講。code
圖片所在目錄對內存的影響?對象
在Android中,圖片的存放目錄和手機的屏幕密度影響圖片最終加載到內存的實際大小,舉個例子:假設咱們的圖片放到xhdpi目錄下,那麼咱們本文中的圖片佔用的內存大小以下.blog
因此,計算圖片佔用內存大小的時候,要考慮圖片所在的目錄跟屏幕密度,這兩個因素其實影響的是圖片的高寬,Android會對圖片進行拉昇跟壓縮。圖片
圖片的內存佔用計算方式爲:圖片高度 * 圖片寬度 * 一個像素佔用的內存大小,因此圖片的高寬若是都變爲原來寬高的2倍,那麼內存將變爲原來的4倍。因此圖片的使用原則能夠總結以下:內存
好比要實現一個線性漸變效果能夠採用如下drawable實現:
加載大圖片時須要對圖片進行壓縮,使用等比例壓縮方法直接在內存中處理圖片。
Options options = new BitmapFactory.Options(); options.inSampleSize = 5; // 原圖的五分之一,設置爲2則爲二分之一 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
這樣作要注意的是,圖片質量會變差,inSampleSize設置的值越大,圖片質量就越差。
有時候咱們取得一張圖片,也許只是爲了得到這個圖片的一些信息,好比圖片的width、height等信息,不須要顯示到界面上,這個時候咱們能夠不把圖片加載到內存中。
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.id.myimage, options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; String imageType = options.outMimeType;
因爲Android外層是使用java,而底層使用的是C語言爲圖片對象分配的內存空間。因此咱們的外部雖然看起來釋放了,但裏層卻並不必定徹底釋放了,咱們使用完圖片後最好再釋放掉裏層的內存空間。
if (!bitmapObject.isRecyled()) { // Bitmap對象沒有被回收 bitmapObject.recycle(); // 釋放 System.gc(); // 提醒系統及時回收 }
RGB(ARGB)
RGB色彩模式是工業界的一種顏色標準,是經過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來獲得各式各樣的顏色的,RGB便是表明紅、綠、藍三個通道的顏色,這個標準幾乎包括了人類視力所能感知的全部顏色,是目前運用最廣的顏色系統之一。在Android中還有包含透明度Alpha的顏色模型,即ARGB。
在不考慮透明度的狀況下,一個像素點的顏色值在計算機中的表示方法有如下3種:
在Java中,float類型的變量佔32位,int類型的變量佔32位,short和char類型的變量都在16位,所以能夠看出,用浮點數表示法編碼一個像素的顏色,內存佔用量是96位即12字節;而用24位整數表示法編碼,只要一個int類型變量,佔用4個字節(高8位空着,低24位用於表示顏色);用16位整數表示法編碼,只要一個short類型變量,佔2個字節;所以能夠看出採用整數表示法編碼顏色值,能夠大大節省內存,固然,顏色質量也會相對低一些。在Android中獲取Bitmap的時候通常也採用整型編碼。
在Android的Bitmap.Config類中,有ARGB_888八、ARGB_444四、RGB565等常量,如今能夠知道它們分別表明了什麼含義。
在Android中系統默認使用的編碼格式是ARGB_8888,因此在文章開頭計算圖片內存大小的時候每一個像素佔用內存大小是4byte,好比採用ARGB_8888編碼載入一張1920*1200的圖片,大概就會佔用1920*1200*4/1024/1024=8.79MB的內存。
採用低內存佔用量的編碼方式,好比Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省內存,好比1920*1200的圖片。
在Android中,對圖片的使用必定要關注,大多數狀況下,佔用內存多,OOM發生都是由於圖片資源使用不當。不要盲目加一個大圖到Android項目中,能使用.9進來使用,並且.9圖自己儘量小,另外能使用繪製實現就不要加一個圖片資源。有些時候,在不影響用戶體驗的狀況下,能夠下降圖片色彩質量,好比不須要透明度的就不要了,有些透明度用肉眼看不出來。