Android 性能優化——之圖片的優化
在Android性能優化中,我們會發現占內存最大的和對性能影響最大的往往是圖片資源,其次是控件資源。相對來說,其他的資源的影響會小一點。這里我就先對圖片資源的優化進行一下講解,如果有什么說的不對的,希望大神指正一下。
1、首先我們可以對圖片進行二次采樣,從本質上減少圖片的內存占用。就是將大圖片縮小之后放入到內存中,以實現減小內存的目的。代碼如下:
1 //創建縮略圖 2 private Bitmap onCreateThumbnail(String filePath2, int i) { 3 4 //得到選項 5 BitmapFactory.Options options=new BitmapFactory.Options(); 6 //設置為不讀內容,值讀取邊界值 7 options.inJustDecodeBounds=true; 8 //通過編輯,得到邊界值,並存入到option中 9 BitmapFactory.decodeFile(filePath2,options); 10 //得到縮放比例 11 int ratiowidth=(options.outWidth)/i; 12 //賦值縮放比例 13 options.inSampleSize=ratiowidth; 14 //設置顯示的圖片格式 15 options.inPreferredConfig=Config.RGB_565; 16 //設置為讀取內容, 17 options.inJustDecodeBounds=false; 18 //得到縮略圖 19 return BitmapFactory.decodeFile(filePath2, options); 20 }
當然現在有很多的第三方框架可以快速的實現這個功能,如Picasso等,其用法只是調用一下方法就可以了,相當對來說更容易(不會的朋友,可以在網上搜一下,很簡單實 用的框架)。
2、其次就是采用三層緩存架構,提高圖片的訪問速度。三層緩存架構是內存-文件-網絡。
內存是訪問速度最快的部分但是分配的空間有限,所以不可能占用太多。其中內存緩存可以采用LRU算法(最近最少使用算法),來確定要刪除內存中的那些圖片,保存那 些圖片。
文件就是將圖片保存到本地,可以使SD卡中,也可以是手機內部存儲中。
網絡就是訪問網絡下載圖片,進行圖片的加載。
3、常見的png,JPG,webp等格式的圖片在設置到UI上之前需要經過解碼過程,而圖片采用不同的碼率,也會造成對內存的占用不同。下面介紹幾種常見的解碼率:
1)ALPHA_8格式的解碼率,此時圖片只有alpha值,沒有RGB值,一個像素占用一個字節,內存占用是最小的,但是也是最不清晰的一種,極易照成畫面失真,不建議使 用。
2)ARGB_4444 格式的解碼率,這種格式的圖片,看起來質量太差,已經不推薦使用。 而強烈推薦使用ARGB_8888來代替。一個像素占用2個字節,alpha(A) 值,Red(R)值,Green(G)值,Blue(B)值各占4個bites 。 共16bites,即2個字節
3)ARGB_8888 格式的解碼率,一個像素占用4個字節,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8個bites , 共32bites , 即4個字節。這是一種高 質量的圖片格式,電腦上普通采用的格式。它也是Android手機上一個BitMap的默認格式。
4)RGB_565格式的解碼率,一個像素占用2個字節,沒有alpha(A)值,即不支持透明和半透明, Red(R)值占5個bites ,Green(G)值占6個bites ,Blue(B)值占5 個bites,共16bites,即2個字節。 對於半透明顏色的圖片來說,該格式的圖片能夠達到比較好的呈現效果,相對於ARGB_8888來說也能減少一半的內存開銷,因此它是一 個不錯的選擇。
總的來說,比較推薦用最后一種,性能較好,且沒有alpha值,系統不用進行二次的渲染,可以很大的提高效率和性能。
4、最后一點,也是圖片優化最重要的一點。重用Bitmap.
我們都知道bitmap會占用大量的內存空間,如下圖:
所以可以重用已存在的bitmap內存區域。通過inBitmap屬性可以使提升Bitmap循環效率。內存使用如下圖:
使用這個屬性,可以告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的bitmap會嘗試去使用之前那張bitmap在heap中所占據的pixel data內存區域,而不是去問內存 重新申請一塊區域來存放bitmap。利用這種特性,即使是上千張的圖片,也只會僅僅只需要占用屏幕所能夠顯示的圖片數 量的內存大小。
代碼:
//得到選項 BitmapFactory.Options options=new BitmapFactory.Options(); options.inBitmap=mCurrentBitmap; mCurrentBitmap=BitmapFactory.decodeFile(filename,options);
使用這個屬性需要注意一下幾個限制條件:
1、在SDK 11 -> 18之間,重用的bitmap大小必須是一致的,例如給inBitmap賦值的圖片大小為100-100,那么新申請的bitmap必須也為 100-100才能夠被重用。從 SDK 19開始,新申請的bitmap大小必須小於或者等於已經賦值過的bitmap大小。
2、新申請的bitmap與舊的bitmap必須有相同的解碼格式,例如大家都是8888的,如果前面的bitmap是8888,那么就不能支持4444與565格式的bitmap了。