在Android系統中,其實操作的是位圖,即:Bitmap。我們知道在windows、macos等一些系統上支持jpg、png、webp等圖片格式。為了提高文件的傳輸以及顯示速度可以把圖片經過算法把文件壓縮成不同的格式,或者使文件變小就可以達到目的。但是在android系統上顯示完全就不是這么回事了。
在Android顯示一張圖片,不管圖片是JPEG、PNG、WEBP格式的都需要把這些圖片解碼成位圖格式后Android系統才能正常的顯示出來。
我們都知道圖片在app中是非常的占用內存的,具體為什么如此占用內存下面就來說到說到,完事后基本上就對如何優化圖片內存有一個大概的方向了。
在Android中一張圖片被解碼成位圖以后其占用運行時內存的大小只和圖片的質量和大小有關系。即:圖片的長度、圖片的寬度、單位像素所占的字節數。
公式如下:Bitmap所占內存=圖片的寬度 * 圖片的高度 * 單位像素所占的字節數(圖片的長度和寬度的單位是像素)
根據以上的公式我們在優化Bitmap的時候大概有兩種思路,當然這兩種思路也可以公用。其原理就是讓三個變量相乘的乘積盡量的小就行了。
1.降低圖片質量(即減少單位像素所占字節數的大小)
2.縮小圖片的大小(寬高)
一、降低圖片質量
Android系統在默認的情況下把圖片解碼成位圖后,會被處理成32bit/像素。即紅、綠、藍、透明通道各8bit(即使有些圖片沒有透明通道依然會被處理掉)。所以我們要更改圖片的質量可以把圖片解碼時的默認bit/像素數處理的小一點。這個時候就需要使用到位圖規格了。下面看一張圖片,如果有小伙伴用過imageloader或者glide或者其他一些處理圖片的開源庫的時候就會非常的熟悉。
以上就是Android系統支持的四種位圖格式。ARGB_8888是android系統默認的其規格是32bit/像素。其ARGB_4444和RGB_565的規格是16bit/像素。所以要優化圖片的規格只需要把系統默認的規格改成這兩個規格就行了。這樣做雖然圖片的內存占用減少了,但是其付出的代價是視覺體驗受損的。因為ARGB_4444和RGB_565減少了圖片的像素數。但是如果能夠根據使用場景靈活的時候這三種規格,其實還是非常不錯的。例如:頭像、小圖可以使用ARGB_4444和RGB_565,在查看清晰的大圖的時候再使用ARGB_8888的規格。
如何更改位圖的默認規格呢?下面給出示例代碼
BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_4444;//把默認規格改成ARGB_444 Bitmap bitmap = BitmapFactory.decodeStream(in,null,options);
二、改變圖片的大小
在某些場景下,手機屏幕上需要顯示的圖片的寬高為:50px*50px,而圖片實際轉換為位圖后的大小為100px*100px。在這種場景下本來我們要開辟的內存為50*50*單位像素所占字節數就夠了。而實際上我們缺開辟出來100*100*單位像素所占字節數。所以這種情況下就造成了顯示內存的嚴重浪費。而且這種問題經常會出現,例如:顯示頭像、顯示縮略圖等場景。
所以我們在開發中盡量把屏幕要顯示的圖片大小和實際上內存中圖片的大小一致就能很好的解決內存的浪費。在Options中為開發者提供了一個inSimpleSize屬性,其會以2的冪函數來縮小圖片。
例如:inSimpleSize=2其圖片大小變為原來的二分之一,inSimpleSize=8,圖片則變為原來的八分之一。示例代碼如下:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_4444;//把默認規格改成ARGB_444 options.inSampleSize = 4;//圖片未原圖的四分之一 Bitmap bitmap = BitmapFactory.decodeStream(in,null,options);
總結:優化Bitmap所占內存最常見,效果最好的就是這兩個策略(降低圖片質量、減小圖片大小)。當然除了這兩種方式還有一些輔助策略,如:更精准的縮放圖片(inScaled、inDensity、inTargetDensity)。再如使用inBitmap屬性來重用Bitmap所占內存。
乖乖在家坐月子😂