mipmap不同的文件夾下圖片的內存占用

概括

上一篇文章提到進行適配的時候,理想的情況是:針對不同密度的設備由設計提供不同的尺寸的圖片,分別放進mipmap的不同文件夾下,以實現基本一致的用戶體驗。但是實際情況是多數公司都只會根據交互圖出一份切圖,我目前的項目也是這樣。那么,此時問題就來了,圖片究竟該放在mipmap-mdpi、mipmap-ndpi、mipmap-xndpi、mipmap-xxndpi、mipmap-xxxndpi中的那個文件夾下呢?

之前我是直接把圖片放在mipmap-hdpi的文件夾下,不同的設備會自動去到該文件夾下找相應的圖片,但是最近突然發現這樣做存在非常大的問題,因為:相同的圖片放在不同的文件夾下在不同的設備上的內存占用是不同的。

具體我們來分析一下:
準備的圖片參數為:1080*520px、32-bit color、文件大小373.32KB的圖片,手機是魅藍note2,1920*1080px,尺寸為5.5英寸,設備像素密度為3。

圖-1.png

主界面

public class MainActivity extends AppCompatActivity {

    private ImageView imgView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imgView = (ImageView) findViewById(R.id.img);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        printImgWH();
    }

    private void printImgWH(){
        if (imgView==null){
            return;
        }
        Drawable drawable = imgView.getDrawable();
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        Bitmap bitmap = bitmapDrawable.getBitmap();
        System.out.println("img width:"+bitmap.getWidth()+";img height:"+bitmap.getHeight());
    }
}

布局界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.zhl.mipmapdemo.MainActivity">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_group_bg"/>

</LinearLayout>

代碼比較簡單。我們分以下的幾種情況進行驗證:

情況1.首先不設置圖片,運行app后內存占用、圖片寬高:

圖-2.png
圖-3.png

結果:app占用內存為17.47M,空閑內存為2.67M.圖片(bitmap)寬高輸出0*0px

情況2.把圖片放在mipmap-xxhdpi文件夾下,運行app后內存占用、圖片寬高:

圖-4.png
圖-5.png

結果:app占用內存為19.61M,空閑內存為0.52M.圖片(bitmap)寬高輸出1080*520px

情況3.把圖片放在mipmap-mdpi文件夾下,運行app后內存占用、圖片寬高:

圖-6.png
圖-7.png

結果:app占用內存為36.43M,空閑內存為3.71M.圖片(bitmap)寬高輸出3240*1560px

情況4.把圖片放在mipmap-hdpi、mipmap-xhdpi、mipmap-xxxhdpi文件夾下,運行app后內存占用、圖片寬高:

這三種情況我就不放截圖了。結果分別是:
hdpi:app占用內存為25.72M,空閑內存為3.71M.圖片寬高(bitmap)輸出2160*1040px
xhdpi:app占用內存為21.96M,空閑內存為3.77M.圖片寬高(bitmap)輸出1620*780px
xxxhdpi:app占用內存為18.68M,空閑內存為1.45M.圖片寬高(bitmap)輸出810*390px

情況5.把圖片放在mipmap-xxhdpi文件夾下,同時設置ImageView的寬高分別為1dp,運行app后內存占用、圖片寬高:

圖-8.png
圖-9.png

結果:app占用內存為19.83M,空閑內存為0.30M.圖片(bitmap)寬高輸出3240*1560px,圖片(ImageView)的寬高輸出為3*3px
注:此種情況是后面加的,因此與情況2的結果有差異,理想情況下app占用內存和空閑內存應與情況2一致。

結果分析:
1、在同一設備上,相同的圖片放在設備像素密度越高的文件夾下,圖片輸出的寬高越小。且根據像素密度的關系,呈現3:2:1.5:1:0.75的比例關系。
2、在同一設備上,相同的圖片放在設備像素密度越高的文件夾下,圖片占用的內存越小。
3、圖片在硬盤上的大小,與之在內存中的大小沒有直接關系。
4、相同像素密度的文件夾下,圖片加載到內存中bitmap的大小不受ImageView大小的影響,即圖片占用的內存大小與圖片(ImageView)的實際大小無關,只與圖片的分辨率有關。

我們以xxhdpi設備上得到的數據進行計算內存占用:
1080*520*4*8/8 byte,即2246.4kb,即2.2464M.所以理論計算此時占用的內容更應該為初始內存加此內存,即17.47+2.2464=19.7164,與實際值19.61基本一致(在誤差范圍內)。

Android中bitmap的默認Config為:ARGB_8888,此config表示每個像素分別由A、R、G、B四個通道表示,每個通道占8bit,所以每一個像素的大小為4*8=32bit,即4kb。

另外,圖片在硬盤存儲時表現的大小,與內存中表現不一致。看到另外一篇博文(結尾附上)解釋的很詳細,是這樣寫的:

存放在硬盤上的圖片文件,會根據各自的壓縮規則進行壓縮,比如Jpeg這種有損壓縮的圖片格式,最常使用可變字長編碼的哈弗曼編碼,會使用哈弗曼樹,也就是最優二叉樹,根據某些數據出現的頻率對數據段編碼,從而減少占用的硬盤大小。

比如說“10111”這個序列在圖片的二進制數據中出現的概率最大,那我們可以用“01”來代替這一段數據,原來5位的數據,用2位就可以表示了,這就是壓縮率60%。當然這只是打個比方,在實際操作中需要考慮“異前綴原則”等編碼的基本原則。

而如果把圖像讀取到內存中就不一樣了,因為我們需要每一個像素都能在屏幕上顯示,所以會把每個像素點都加載至內存中,不會對相同像素進行壓縮或者是替換,所以你也應該能明白前面提到的Bitmap占用內存大小的計算公式的由來了。

結論

<p>Android設備加載圖片時,它會首先去到與該設備像素密度一致的文件夾下找圖片,如果找不到,他會依次到其他文件夾下去找,但是最終的顯示結果會進行縮放,規則是根據設備像素密度和對應文件夾的像素密度的反比縮放圖片。即當訪問的文件夾的代表像素密度更大時,圖片表現出來的寬高會更小,內存占用也會更小。</p>
所以,當我們只能為app提供一套切圖時,優先的考慮是盡可能的提供最高設備像素密度下的切圖,并放在相應的文件夾下,即xxxhdpi設備下的切圖,其次考慮提供主流像素密度設備的切圖,目前我項目中提供的均為1920*1080px,xxhdpi下的切圖。這種切圖在xxxhdpi設備下會進行一定的縮小顯示,需要注意最終呈現效果。
</br>
參考鏈接:
http://blog.csdn.net/zhaokaiqiang1992/article/details/49787117

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容