本文大纲:
android项目资源中对于drawable文件夹可以分为以下类型的文件夹:
我们大概知道这些是存放不同分辨率的图片的,高分辨率的图片要放在高密度的文件夹里,低分辨率的图片要放在低密度的文件夹里。但是考虑下面几个问题:
表1:
注意密度是根据设备来决定的,设备密度的获取方式:
float xdpi = context.getResources().getDisplayMetrics().xdpi;
float ydpi = context.getResources().getDisplayMetrics().ydpi;
假设此时的设备密度是480dpi, 那么xxhdpi会被认为是程序的匹配密度目录,默认优先使用xxhdpi文件下的图片。
每种密度下的图片设计成什么尺寸Android也是给出了建议:
表2:
上面是andriod给出的建议尺寸,实际中可能会不同。但是一定要记住一下几点:
延伸问题:如果不匹配,那么缩放或者放大多少呢?
公式: scale=设备dpi / 图片所在drawable目录对应的最大dpi
举个例子,假设当前的设备密度是 480dpi, 一张72x72的图片分别放在drawable-xxhdpi和drawable-xhdp,两种情况下图片各占多少内存?(假设现在是RGB565格式)
分析:
1.图片放在drawable-xxhdpi:
由表1可知xxhdpi对应的最大dpi为480dpi
scale = 设备密度/xxhdpi对应的最大dpi = 480dpi/480dpi = 1
也就是说这种情况下不会进行缩放,因为图片恰好放在了设备匹配的文件夹中。此时图片占用的内存= 72 * 72 * 2 = 10368
2.图片放在drawable-xhdpi:
由表1可知xhdpi对应的最大dpi为320dpi
scale = 设备密度/xhdpi对应的最大dpi = 480dpi/320dpi =1.5
这种情况下要进行放大,因为低于设备匹配目录,此时图片占用的内存= 72 * 72 * 2 * 1.5 = 15552
所以,我们知道,如果在开发时不恰当的将高分辨的图片放在低密度的文件夹里,很可能在高密度的设备上显示的时候会oom,因为它们会进行放大!!
图1:
查找步骤:
说明:
简单介绍bitmap, 它是android的图片资源或文件在内存中的展现方式。
/**
*每个像素存储为一个半透明(alpha)通道。
*这对于有效地存储掩码非常有用。
*不存储颜色信息。
*使用这种配置,每个像素需要1字节的内存。
* /
Bitmap.Config.ALPHA_8
/ * *
*每个像素存储在2个字节,只有RGB通道
*编码:红色是存储5位精度(32可能
*值),绿色是存储与6位精度(64可能
*值)和蓝色是存储与5位精度。
*
*根据不同的情况,此配置可能会产生轻微的可视工件
*关于源的配置。例如,没有
*犹豫不决,结果可能会显示出一抹绿色。得到更好的
*结果应用抖动。
*
*此配置在使用不透明位图时可能很有用
*不需要高的色彩保真度。
*
* 使用此公式压缩成16位:
* < pre类= " prettyprint " >
*短颜色= (R & 0 x1f) < < 11 | (G & 0 x3f) < < 5 | (B & 0 x1f);
* < / pre >
Bitmap.Config.RGB_565
/ * *
*每个像素存储在2个字节。三个RGB彩色通道
*和alpha通道(半透明)存储为4位
精度(16个可能的值)
*
*如果应用程序需要,此配置非常有用
*存储半透明信息,但也需要保存
*内存。
*
*建议使用{@link #ARGB_8888}代替这个
*配置。
*
*注意:在{@link android.os.Build.VERSION_CODES#KITKAT}时,
*使用此配置创建的任何位图都将被创建
*使用{@link #ARGB_8888}代替。
*
* @deprecated,因为这个配置的质量很差,
*建议使用{@link #ARGB_8888}。
* /
Bitmap.Config.ARGB_4444
/ * *
*每个像素存储4个字节。每个频道(RGB和alpha)
*用于半透明)以8位精度存储(256位)
*可能值。)
*
这种配置非常灵活,提供了最好的
*质量。只要可能就应该使用它。
*
* 使用这个公式打包成32位:
* < pre类= " prettyprint " >
* int颜色= (& 0 xff) < < 24 | (B & 0 xff) < < 16 | (G & 0 xff) < < 8 | (R & 0 xff);
* < / pre >
* /
Bitmap.Config.ARGB_8888
/ * *
*每个像素存储在8个字节。每个频道(RGB和alpha)
*用于半透明)存储为a
* {@link android.util。半精度浮点值}。
*
*此配置特别适合宽色域和
* HDR的内容。
*
* 使用这个公式压缩成64位:
* < pre类= " prettyprint " >
* long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff);
* < / pre >
* /
Bitmap.Config.RGBA_F16
/ * *
*特殊配置,当位图只存储在图形内存。
该配置中的位图总是不可变的。
*
*这是最佳的情况下,当与位图的唯一操作是绘制它在a
*屏幕上。
* /
Bitmap.Config.HARDWARE
在加载图片的时候默认使用ARGB_8888,可以指定颜色格式,通过BitpamOption设置
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = ARGB_4444;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), img, options);
Bitmap的信息:
// 一行占用多少像素
int width = bitmap.getWidth();
// 一列占用多少像素
int height = bitmap.getHeight();
// 一行占用多少字节
int rowBytes = bitmap.getRowBytes();
// 可用于存储此位图像素的最小字节数 它等于 rowBytes * height
int byteCount = bitmap.getByteCount();
// 用于存储位图像素的已分配内存的大小。
int allocationByteCount = bitmap.getAllocationByteCount();
说明:
基于上面的基础知识,我们密度为480dpi的设备上,将一张 66x71的图片分别放在drawable不同密度的文件夹中,进行内存占用情况的测试。
推测:
图片放在drawable-xxhdpi或者drawable-nodpi中时内存占用为原始大小,其他情况会缩放。
验证:
首先来编写测试的代码:
// 获取设备的dpi
float xdpi = context.getResources().getDisplayMetrics().xdpi;
float ydpi = context.getResources().getDisplayMetrics().ydpi;
// 加载图片查看内存
LogUtil.E("=====测试,设备密度: xdpi:"+xdpi+",ydpi:"+ydpi+", 使用ARGB8888模式加载66x71的图片======");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), img, options);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int rowBytes = bitmap.getRowBytes();
int byteCount = bitmap.getByteCount();
int allocationByteCount = bitmap.getAllocationByteCount();
LogUtil.E("加载结果:");
LogUtil.E("width-->" + width);
LogUtil.E("height-->" + height);
LogUtil.E("rowBytes-->" + rowBytes);
LogUtil.E("byteCount-->" + byteCount);
LogUtil.E("allocationByteCount-->" + allocationByteCount);
图片放在 drawable下的输出情况:
=====测试,设备密度: xdpi:480.0,ydpi:480.0, 使用ARGB8888模式加载66x71的图片======
加载结果:
width-->198
height-->213
rowBytes-->792
byteCount-->168696
allocationByteCount-->168696
图片放在 drawable-mdpi下的输出情况:
=====测试,设备密度: xdpi:480.0,ydpi:480.0, 使用ARGB8888模式加载66x71的图片======
加载结果:
width-->198
height-->213
rowBytes-->792
byteCount-->168696
allocationByteCount-->168696
图片放在 drawable-xhdpi下的输出情况:
=====测试,设备密度: xdpi:480.0,ydpi:480.0, 使用ARGB8888模式加载66x71的图片======
加载结果:
width-->99
height-->107
rowBytes-->396
byteCount-->42372
allocationByteCount-->42372
图片放在 drawable-xxhdpi下的输出情况:
=====测试,设备密度: xdpi:480.0,ydpi:480.0, 使用ARGB8888模式加载66x71的图片======
加载结果:
width-->66
height-->71
rowBytes-->264
byteCount-->18744
allocationByteCount-->18744
图片放在 drawable-xxxhdpi下的输出情况:
=====测试,设备密度: xdpi:480.0,ydpi:480.0, 使用ARGB8888模式加载66x71的图片======
加载结果:
width-->50
height-->53
rowBytes-->200
byteCount-->10600
allocationByteCount-->10600
图片放在 drawable-nodpi下的输出情况:
=====测试,设备密度: xdpi:480.0,ydpi:480.0, 使用ARGB8888模式加载66x71的图片======
加载结果:
width-->66
height-->71
rowBytes-->264
byteCount-->18744
allocationByteCount-->18744