OOM 现象通常出现在用到很多图片 或者很大图片的APP开发中,就是 我们的APP要申请一块内存在装图片的时候 。系统觉得已经够用了 其实肯定是不够用的。他不愿意给我们的APP 好、更多的内存 ,这个时候 就会出现OOM 异常。如果程序没有捕捉到异常 ,肯定就要崩溃的。
图像的来源 一般有这几种:
从网络加载:
从文件读取:
从资源文件加载。
这三种情况 我们一般使用BitmapFactory的:decodeStream,decodeFile,decodeResource,这三个函数来获取到bitmap然后再调用ImageView的setImageBitmap函数进行展现。
我们的内存就是去bitmap里了,BitmapFactory的每个decode函数都会生成一个bitmap对象,用于存放解码后的图像,然后返回该引用。如果图像数据较大就会造成bitmap对象申请的内存较多,如果图像过多就会造成内存不够用自然就会出现out of memory的现象。
那怎么才是正确的加载图像呢
我们知道我们的手机屏幕有着一定的分辨率(如:840*480),图像也有自己的像素(如高清图片:1080*720)。如果将一张840*480的图片加载铺满840*480的屏幕上这就是最合适的了,此时显示效果最好。如果将一张1080*720的图像放到840*480的屏幕并不会得到更好的显示效果(和840*480的图像显示效果是一致的),反而会浪费更多的内存。
我们一般的做法是将一张网络获取的照片或拍摄的照片放到一个一定大小的控件上面进行展现。这里就以nexus 5x手机拍摄的照片为例说明,其摄像头的像素为1300万(拍摄图像的分辨率为4032×3024),而屏幕的分辨率为1920x1080。其摄像头的分辨率要比屏幕的分辨率大得多,如果不对图像进行处理就直接显示在屏幕上,就会浪费掉非常多的内存(如果内存不够用直接就oom了),而且并没有达到更好的显示效果。
为了减少内存的开销,我们在加载图像时就应该参照控件(如:263pixel*263pixel)的宽高像素来获取合适大小的bitmap。
建立个界面:就是一个用拍照的Button和一个用于显示头像的ImageView,其中ImageView大小为100dp*100dp.
java代码这里简单的实现了一个调用相机的功能,点击button调用系统自带相机,然后再onActivityResult里加载拍摄的照片就可以了
这里我们重点关注加载照片的部分:
这里提供了两种加载照片的方式:1.不做任何处理直接加载。2.就是调用我们之前写的代码缩放后加载(这里的BitmapUtils就是将之前的代码封装成的一个工具类)。
我们一般的做法是将一张网络获取的照片或拍摄的照片放到一个一定大小的控件上面进行展现。这里就以nexus 5x手机拍摄的照片为例说明,其摄像头的像素为1300万(拍摄图像的分辨率为4032×3024),而屏幕的分辨率为1920x1080。其摄像头的分辨率要比屏幕的分辨率大得多,如果不对图像进行处理就直接显示在屏幕上,就会浪费掉非常多的内存(如果内存不够用直接就oom了),而且并没有达到更好的显示效果。
为了减少内存的开销,我们在加载图像时就应该参照控件(如:263pixel*263pixel)的宽高像素来获取合适大小的bitmap。
建立个界面:就是一个用拍照的Button和一个用于显示头像的ImageView,其中ImageView大小为100dp*100dp.
java代码这里简单的实现了一个调用相机的功能,点击button调用系统自带相机,然后再onActivityResult里加载拍摄的照片就可以了
这里我们重点关注加载照片的部分:
这里提供了两种加载照片的方式:1.不做任何处理直接加载。2.就是调用我们之前写的代码缩放后加载(这里的BitmapUtils就是将之前的代码封装成的一个工具类)。
对于不同手机运行直接加载图像方式的时候可能会不能正在运行,直接就OOM了。
不同大小的图片需要做成同一个高度的的缩略图(如100px),而且要保证图片不失真,那怎么办?总不能将原始图片加载到内存中再进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止100K?