图片被渲染到屏幕前,会被作为纹理传送到GPU(承担输出显示图形的任务),这意味着每张图片会同时占用CPU和GPU内存。
安卓显示图片和图片文件大小无关,显示图片前会把图片解码成位图Bitmap格式,而位图格式只和位图的属性相关,压缩格式仅仅是减小文件大小。
剩余内存大于图片所需内存,但如果剩余内存最大连续内存小于位图内存,仍会触发GC,从其他位置释放内存。
我们读取的是 drawable 目录下面的图片,用的是 decodeResource 方法,该方法本质上就两步:
- 读取原始资源,这个调用了 Resource.openRawResource 方法,这个方法调用完成之后会对 TypedValue 进行赋值,其中包含了原始资源的 density 等信息;
- 调用 decodeResourceStream 对原始资源进行解码和适配。这个过程实际上就是原始资源的 density 到屏幕 density 的一个映射
占用内存计算
- 1(dp)=density (px)
- densityDpi 是屏幕每英寸对应多少个点(不是像素点)
- density=densityDpi / 160
占用内存 = 图片宽度 *图片高度 *单位像素占用的字节数;
- 图片宽度 = bitmap.getWidth() = 图片原始宽度* scale + 0.5f
- 图片高度 = bitmap.getHeight() = 图片原始高度* scale + 0.5f
- scale= densityDpi / density
(解码出来后bitmap的)density这个值跟这张图片的放置的目录有关(比如 hdpi 是240,xxhdpi 是480)
densityDpi(屏幕的 density) - 像素占用字节:ARGB_8888-4byte,ARGB4444-2byte,RGB565 -2byte,Alpha8-1byte
图片的占用内存与屏幕密度(densityDpi)、图片存放位置、图片格式有关
![](https://img.haomeiwen.com/i6274589/7390eda47dc36f93.png)
备注:对于加载非资源文件(如网络图片),如果没有设置options则density默认为设备密度。
举个例子
一张522*686的PNG 图片,我把它放到 drawable-xxhdpi 目录下,在三星s6上加载,densityDpi对应 xxhdpi 为480,三星s6的densityDpi 为640:
scaledWidth = int( 522 * 640 / 480f + 0.5) = int(696.5) = 696
scaledHeight = int( 686 * 640 / 480f + 0.5) = int(915.16666…) = 915
内存大小=scaledWidth *scaledHeight *4 = 915 * 696 * 4 = 2547360
参考:
Android - Bitmap-内存分析
[Android性能优化:Bitmap详解&你的Bitmap占多大内存?)
网友评论