学而不思则罔,思而不学则殆
Android 你还在为图片放哪儿纠结吗?图片资源文件夹加载规律
引言
市面上Android机型五花八门,因此开发的时候的UI设计稿理论上需要提供所有的屏幕密度对应的素材。
如下是像素密度和对应的资源文件夹。
Type | file | dpi | Picture |
---|---|---|---|
ldpi | drawable-ldpi | 0.75 | 75px*75px |
mdpi | drawable-mdpi | 1 | 100px*100px |
hdpi | drawable-hdpi | 1.5 | 150px*150px |
xhdpi | drawable-xhdpi | 2 | 200px*200px |
xxhdpi | drawable-xxhdpi | 3 | 300px*300px |
xxxhdpi | drawable-xxxhdpi | 4 | 400px*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 Heap | Native Heap | Code | Stack | Graphics | Private Other | System | TOTAL |
---|---|---|---|---|---|---|---|---|---|---|
未设置图片 | - | - | 8348 | 13680 | 4500 | 80 | 8867 | 1560 | 6724 | 43759 |
drawable-mdpi | 2952*1566 | 17.635M | 8516 | 36868 | 4296 | 92 | 33943 | 1688 | 6709 | 92112 |
drawable-hdpi | 1968*1044 | 7.838M | 8584 | 24404 | 4304 | 92 | 22463 | 1704 | 6683 | 68189 |
drawable-xhdpi | 1476*783 | 4.409M | 8896 | 21000 | 3560 | 92 | 18555 | 1532 | 6713 | 60353 |
drawable-xxhdpi | 984*522 | 1.96M | 8344 | 18188 | 4692 | 92 | 16199 | 1508 | 6845 | 55868 |
drawable-xxxhdpi | 738*392 | 1.104M | 8356 | 16940 | 4444 | 92 | 15151 | 1596 | 6698 | 53277 |
第一点疑惑:当我们放置的图片资源在越低的像素密度文件夹中,图片加载出来的宽高越高,内存消耗越大呢?
这个疑惑,我们就通过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层的内存。不同分辨率的静态资源图片放在不同的文件夹下面,不要随便放,会引起内存的异常。
文章还有很多不成熟,欢迎大佬们提提意见,有不对的欢迎评论指出!!!