Android 你還在為圖片放哪兒糾結嗎?圖片資原始檔夾載入規律

珍心發表於2020-11-27

學而不思則罔,思而不學則殆

Android 你還在為圖片放哪兒糾結嗎?圖片資原始檔夾載入規律


引言

市面上Android機型五花八門,因此開發的時候的UI設計稿理論上需要提供所有的螢幕密度對應的素材。
如下是畫素密度和對應的資原始檔夾。

TypefiledpiPicture
ldpidrawable-ldpi0.7575px*75px
mdpidrawable-mdpi1100px*100px
hdpidrawable-hdpi1.5150px*150px
xhdpidrawable-xhdpi2200px*200px
xxhdpidrawable-xxhdpi3300px*300px
xxxhdpidrawable-xxxhdpi4400px*400px

假如我們有一個icon是100dp100dp,那麼為了適配所有的手機密度,理論上我們需要提供這六種畫素密度對應的圖片。分別是75px75px … 400px*400px.

但是實際開發中我們不會這麼做,為什麼呢?每張圖片都做6套的話,會造成apk體積過大,尤其是手機的內建應用廠商對每個系統應用的大小都有嚴格的要求。

一般情況下只會放置一套圖示。
那麼這套圖表放置在哪個資原始檔夾下呢?

資源怎麼放置

研究怎麼放置之前,我們先來測試一下,我的一套圖放置在不同資原始檔夾下,在同一個手機上的展示效果,記錄其展示的圖片大小和記憶體消耗。

圖片大小:984*522
手機情況:xxhdpi, 3dpi

也就是說該手機的圖片需要放置在drawable-xxhdpi資原始檔下面圖片才是原圖展示,而不會發生縮放。

記憶體情況通過如下命令可以檢視

adb shell dumpsys meminfo com.achievo.bitmademo

圖片展示大小記憶體情況統計

改圖統計的規則,資源圖片只放在一個資原始檔夾下面,其他資原始檔夾不放置該資源圖片。如下是展示圖片後統計的Bitmap圖片大小和記憶體消耗統計。

    public void test(View view) {
        ycy = BitmapFactory.decodeResource(getResources(), R.drawable.ycy);
        imageView.setImageBitmap(ycy);
        int count = ycy.getAllocationByteCount();
        Log.d("zhangyu1127", "[" + ycy.getWidth() + " " + ycy.getHeight() + "] " + (count / 1024f / 1024f) + "M");
    }
測試type圖片大小圖片記憶體消耗Java HeapNative HeapCodeStackGraphicsPrivate OtherSystemTOTAL
未設定圖片--83481368045008088671560672443759
drawable-mdpi2952*156617.635M851636868429692339431688670992112
drawable-hdpi1968*10447.838M858424404430492224631704668368189
drawable-xhdpi1476*7834.409M889621000356092185551532671360353
drawable-xxhdpi984*5221.96M834418188469292161991508684555868
drawable-xxxhdpi738*3921.104M835616940444492151511596669853277

第一點疑惑:當我們放置的圖片資源在越低的畫素密度資料夾中,圖片載入出來的寬高越高,記憶體消耗越大呢?

這個疑惑,我們就通過hdpi來解答一下,我們放置一個984 * 522的圖片在drawable-hdpi資原始檔夾下,在手機畫素密度為xxhdpi, 3dpi的手機上展示。那麼你想一下,如果我們在該手機上的每個資原始檔都放置圖片,按照螢幕密度。現在你在hdpi = 1.5dpi的手機中放置了984 * 522的圖片,那麼等比例你是不是也需要在xxhdpi = 3dpi的資原始檔夾下放一張1968 * 1044 的圖片呢!
所以就是表格中統計的1968 * 1044圖片大小。
通過這個你也就發現,一般情況下我們把圖片資源放置在螢幕密度越小的資原始檔夾下面,當使用者的手機實際螢幕密度越大的時候,需要載入的圖片會放大越多。因為按照比例,圖片會越大。

所以一般只有一套圖的時候,資源主要放置在drawable-xxhdpi = 3 dpi的資原始檔夾下面。主要有兩點考慮。第一點,該螢幕密度的手機目前佔據市場主流,符合大部分的要求。另一點是,就算需要縮放,那麼也只是針對dpi>3的會放大x/3倍。其他的都是縮小展示,也不會有記憶體消耗過多的情況發生。

第二點疑惑:Java Heap內怎麼消耗變化,而主要是Native Heap和Graphics變化最多呢?

通過表格可看出,對於不同解析度,Java層記憶體消耗一致,沒什麼變化,而是消耗了native記憶體+Graphics。說明圖片載入主要消耗的是Native層的記憶體,而不是Java層的記憶體。

結論

通過該篇文章測試我們瞭解了不同的螢幕密度下的圖片資源載入到不同手機上的展示情況和記憶體消耗規律。還有就是圖片載入一般消耗的是Native層的記憶體。不同解析度的靜態資源圖片放在不同的資料夾下面,不要隨便放,會引起記憶體的異常。

文章還有很多不成熟,歡迎大佬們提提意見,有不對的歡迎評論指出!!!

相關文章