Android 百问之 OOM

OOM

OOM : OutOfMemoryError ,即应用所需要使用的内存超过了系统分配给应用的最大内存。
移动设备因本身设备资源受限,不可能给单个应用分配过多的内存。因此,当应用所需要使用的内存超过分配的最大内存,就会 OOM 。

两种常见的 OOM 错误

  1. 过大的内存分配 。
  2. 内存泄露(Memory leaks, 即应用未释放已经不再使用的内存)。

过大的内存分配

如果打开一个单独页面或加载一个单独图片的时候导致了 OOM , 那么应用可能加载了一个不必要的大图。
加载一张图片所需的内存为 宽*高*每个像素的字节数 ,每个像素的字节数取决于显示图片所使用的 Bitmap.config 。对 ARGB_8888 的位图来说,
每个像素所占大小为 4 个字节,即 一张1080P的图片所占内存为 1080 * 1920 * 4 约占 8M 内存。图片越大,所占内存越多。
其中:
Bitmap.Config ARGB_4444:一个像素占用2个字节。
Bitmap.Config ARGB_8888:一个像素占用4个字节个字节。
Bitmap.Config RGB_565:一个像素占用2个字节。
Bitmap.Config ALPHA_8:只有透明度,没有颜色,一个像素占用一个字节。

列表页加载图片的处理

像微博或微信 图片九宫格列表页, 如果你直接加载原图,并且快速滑动,很容易 OOM 掉。
解决方法有两种 :
(1) 服务器返回指定格式的图片,例如列表页加载缩略图使用 160*160 分辨率的图片(一般 CDN 厂商都支持该服务)。
(2) 服务端不处理,客户端加载指定大小的图片(例如 160*160 的图片)到内存当中。客户端异步处理,不加载原图到内存,加载裁剪后的图片到内存当中。第三方图片框架,如 Glide 都是支持的。

原图页加载图片的处理

有时候我们不可避免的需要加载原图 ,如用户点击缩略图后,需要显示原图。
这个时候仍然需要对图片进行处理。
如果原图是小分辨图片,一般不需要额外不处理。
如果原图是高清图,例如 : 1080P 以上 或者超长图片(如上万分辨率的图片),此时如果不处理,直接加载到内存中,很容易 OOM 掉。

解决方法 :
有的同学可能想到上面的处理方式, 指定图片的分辨率为 (1080*1920)交由服务器处理 , 这是一种处理方式。但是因为要显示原图,所以如果是超长图的话,那么图片不能 完全显示,因此不采取这种处理方式。
(1) 我们可以异步拿到 Bitmap 对象, BitmapFactory.Options.inSampleSize 对图片进行等比例的缩放,比如客户端设置竖直最大分辨率为 7680,对其原分辨率做等比例缩放到最接近这个值,但需要注意的是 inSampleSize只能是2的整数次幂,如果不是的话,向下取得最大的2的整数次幂。另外对于超长图,我们可以设置其颜色格式 , 例如指定为 ARGB_4444 减少在内存中的占用,但相应的图片质量有所下降。
(2) 如果不想要使用等比例缩放的,可以通过 Bitmap.createBitmap 创建指定大小的 Bitmap。
(3) 长图超过了整个屏幕,因此同一时间,我们不需要全部显示,因此我们可以只显示图片的某一部分区域,通过 BitmapRegionDecoder 。滑动的时候,边解析边显示。

内存泄漏

关于内存泄漏 ,可以参考我之前分析的文章 Android百问之内存泄漏 。

参考链接 :
https://blog.csdn.net/lmj623565791/article/details/49300989

猜你喜欢

转载自blog.csdn.net/stupid56862/article/details/80488884
OOM