https://blog.csdn.net/BUG_delete/article/details/79557939
簡介
Android中經常要通過ImageView進行圖片資源顯示。在加載圖片時,首先要考慮的兩個因素就是體驗問題和性能問題。
其中,體驗問題是指圖片顯示的是否正確(例如Universal-Image-Loader在適配Adapter圖片資源時會導致圖片顯示錯位),分辨率是否合適等。而體驗問題主要是指圖片加載速度,以及更加重要的圖片加載的內存占用問題。本文重點介紹ImageView加載圖片中的內存占用問題。
問題
在開發的過程中,經常會發現因為加載圖片而引起的Out of Memory(OOM)問題,有的時候會很奇怪,明明加載的圖片只有幾十K,為什么就會導致OOM呢?另外在圖片資源設置過程中,只放置某一個dpi文件夾(例如drawable-xxhdpi文件夾)的資源,在不同設備中對ImageView占用會有影響嗎?下面會對圖片加載的內存占用相關問題進行展開分析。
概念描述
首先,圖片對內存的占用是一個疊加的過程,也就是說圖片資源不是及時釋放的,使用過的圖片在回收過程中可能會有一定程度的延遲。此外,很多時候圖片所依附的Activity是出于當前Activity棧底的狀態,再GC回收過程,這樣的bitmap資源會被認為是活躍狀態的,不會被Android系統回收。
另外一方面,Android中圖片加載到內存中的內存占用跟圖片的實際大小沒有直接的關系,甚至于圖片的實際像素尺寸也沒有直接的關系。
在這里,首先要介紹幾個概念(以圖片A:尺寸60*60 大小2.02K為例):
- 圖像尺寸:表示圖像在硬盤中的原始尺寸,本例中為60*60;
- 圖像大小:表示圖像在占據硬盤容量大小,本例中為2.02K;
- bitmap尺寸:表示圖像以bitmap的形式存在內存中的實際尺寸;
- 顯示尺寸:表示圖像在UI上顯示的實際尺寸;
- 內存占用:表示加載的圖片以bitmap的形式在內存中的實際占用。
其中,bitmap尺寸和內存占用可以通過下面的方法得到:
/**** 計算ImageView中加載圖片的具體尺寸和內存占用大小* @param imageView*/private void calculateBitmapInfo(ImageView imageView) {Drawable drawable = imageView.getDrawable();if (drawable != null) {BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;Bitmap bitmap = bitmapDrawable.getBitmap();Log.d(TAG, " bitmap width = " + bitmap.getWidth() + " bitmap height = " + bitmap.getHeight());Log.d(TAG, " memory usage = " + bitmap.getAllocationByteCount());/**bitmap.getByteCount()方法不再使用*/} else {Log.d(TAG, "drawable is null!");}}
具體分析
為了明確這個問題,我們做了以下的幾組實驗對比,具體如下:
實驗1
測試方案:將尺寸為圖片A(尺寸60 * 60 大小2.02K),圖片B(尺寸60 * 60 大小1.63K),將圖片均放入drawable-xxhdpi文件夾,圖片顯示尺寸采用wrap_content,用華為mate 9(xxhdpi)手機進行測試;
測試結果:二者內存占用均為14400Byte,bitmap尺寸為60*60;
結果分析:說明內存占用單獨與圖片原始大小沒有關系。
實驗2
測試方案:將將尺寸為圖片A(尺寸60 * 60 大小2.02K)放入drawable-xxhdpi文件夾,圖片顯示尺寸設置為30dp * 30dp和60dp * 60dp,分別用mate 9手機進行測試;
測試結果:內存占用均為14400Byte,bitmap尺寸均為60*60;
結果分析:說明內存占用與圖片的實際顯示尺寸沒有關系。
實驗3
測試方案3:將將尺寸為圖片A(尺寸60*60 大小2.02K)放入drawable和drawable-xxhdpi文件夾,圖片顯示尺寸采用wrap_content,分別用mate 9手機進行測試;
測試結果:內存占用分別為129600Byte和14400Byte,圖片在ImageView中的bitmap尺寸為180 * 180和60 * 60;
結果分析:說明內存占用與圖片的原始尺寸沒有關系,與bitmap尺寸有密切的關系。