导航:首页 > 操作系统 > androidbitmap内存溢出

androidbitmap内存溢出

发布时间:2023-02-15 11:11:28

‘壹’ android Bitmap 内存以及OOM问题讨论

都知道在Android中, 每个应用所使用的内存是有限的,现在的手机通常最大的内存使用为256M, 目前还没发现Android中一个应用的最大内存分配超过256M的(经测试华为手机的最大内存是385M)

相关API:

ActivityManager.getMemoryClass(),首先获取系统服务中的ActivityManager

如下:

(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

可以获取到相关信息

最近一直被项目的OOM问题困扰, 在网上查阅相关资料,前前后后读了不下于30篇,这些篇幅讲解的东西都是千篇一律,并没有解决到实际问题

也在慕课网学习了内存优化章节

这是慕课网讲师的PPT,我截屏的

这里来仔细分析一下:

第一个,  注意临时Bitmap对象的及时回收, 来看下相关API

直接上图

经过我无数次的使用Android studio工具自带的MAT分析工具后, 得出一个很严谨的结论, 此方法并不奏效...

Android中Bitmap的内存存放在堆区, Google 的Bitmap的recycle方法注释也可以了解到

Android历史版本不是很清楚, 据说Android3.0之前Bitmap是存放在native区域,可以进行手动释放,然而3.0之后Bitmap是存放在Java层的堆区,没错是heap, 内存管理直接交由系统GC管理,你还这样释放资源有意义?无非是给自己的一点心理安慰罢了, 告诉你没卵用

又有人在说要释放内存使用System.gc() ???  对就是主动触发垃圾回收,这个API是开发者自行调用的吗?那么系统管理内存还有什么意义?这不是误人子弟吗,这个API不能调用的, 因为没卵用的, 具体自己参照MAT工具自行分析.即便垃圾回收真的被触发了, 所有线程停滞由系统来清理垃圾, 造成的后果是严重卡顿!!!

再看一个API:

我在网上苦苦追寻内存过高的问题后,发现了这个API,经过无数次实践后我得出一个结论,没卵用...开发者可以抛弃它

综上所诉, 第一点讲解的内存优化问题可以直接PASS掉, 无非给自己一点心理安慰: 我已经处理好了内存问题, 程序不会OOM?

第二点. 避免Bitmap的浪费

直接说结论, 这个是非常行之有效的,并且是一定能解决问题的

具体怎么操作呢? 自己实现LruCache这个类, 就是这么弄, 原理就是解码复用, 在内存中已经解码好的Bitmap直接拿出来使用, 没有的在加载到内存进行解析, 这个非常有效,但是并不能让你避免OOM

第三点, try-catch某些大内存分配的操作

这点上,我又要开始疑问了, 我Java功底不是很好

Java中发生内存溢出时,抛出的是OutOfMemoryError, 它的父类是VirtualMachineError

这玩意能catch住? 它属于Error范畴, 你能捕获?请Java大神出来说一下,我解释不清楚

第四点, 加载Bitmap 缩放比例, 解码格式, 局部加载

先来分析一下缩放比例:

按照市面上主流的手机分辨率来分析现在Android主流的分辨率是1920X1080, 如果一个ImageView控件刚好就是屏幕全屏,怎么说?直接占用掉8M内存, 想想一个实际的需求情况

一个查看大图的页面, 不断的关闭,打开查看新的大图,问题就来了,内存一直在暴增,迟早会突破界限OOM掉

分辨率是2K屏呢? 更恐怖了, 随着手机设备的屏幕分辨率提升, 加载图像需要的内存也是倍增的, 因为应用的最大内存并没有增加

结论: 缩放比例可以有效的降低内存占用问题, 但不是绝对的救命稻草, 该缩放的还是要缩放,而且必须缩放,就是采样  现在通常都是图片加载框架来完成,类似Glide.Picasso,Fresco等,他们可以帮助你减少工作量, 内存问题还是存在

再来分析一下解码格式:

这个跟缩放比例效果差不多, 只是同样的分辨率的图片加载到内存中时占用内存减少了

比如ARGB_8888 共32位

RGB_565  共16位

ARGB_4444 共16位

很明显这样格式图片加载的内存情况是ARGB_8888是其他格式的两倍内存

另外的问题是ARGB_8888看起来很清晰的, 其它的看起来图片有种糊了的感觉,自己选择吧

结论, 降低内存占用非常有效

最后一个是局部加载, 并没有怎么使用到,也不清楚就不说了

最后还有一个方法避免OOM, 开启largeHeap属性, 但是但是, 以前我们开启这个属性后被Oppo应用市场认定为占用内存过高, 不建议用户安装......所以我们又取消了!

总的来说, Bitmap在内存是变现的是不可控, 我项目OOM问题一直没有得到有效解决,因为图片编辑视频编辑之类的功能占用内存过高,继续使用OOM是必然的, 跟IOS的同学交流了一番,他们说IOS的应用内存可以占用到1个G以上, 轻松跑到500M是没问题的, IOS的内存机制可以持续给内存使用, 具体我也不清楚,并且他们可以手动释放内存?malloc, free这样子?

如果大家有比较好的方案,还望留言交流互相帮助 [笑脸.gif]

补充: Android8.0开始Bitmap数据内存存在native层, 单个应用可用的内存显着增长, 极大的降低了OOM的概率(2018年3月22日)

‘贰’ Android createBitmap创建大尺寸图像时,内存溢出out of memory(OOM)

BitmapFactory.Options bfOptions=new BitmapFactory.Options();
bfOptions.inDither=false;//使图片不抖动。不是很懂
bfOptions.inPurgeable=true;//使得内存可以被回收
bfOptions.inTempStorage=new byte[12 * 1024]; //临时存储
File file = new File(path);//path:图片的绝对地址
FileInputStream fs=null;
try {
fs = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bmp = null;
if(fs != null) {
try {
bmp = BitmapFactory.decodeFileDescriptor(fs.getFD(), null, bfOptions); //这样莫非就让bmp到了临时存储的位置?
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fs!=null) {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

}
转的。
http://wenku..com/view/c7b20053ad02de80d4d840f9.html

‘叁’ 如何定位和解决Android的内存溢出问题(大总

一、定位内存泄漏:
可以用LeakCanary:检测所有的内存泄漏
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0509/2854.html
二、解决:
1.对各种流,文件资源这些比如:InputStream/OutputStream,SQLiteOpenHelper,SQLiteDatabase,Cursor,文件,I/O,Bitmap图片等操作等都应该记得显示关闭。

2.尽量避免static成员变量引用资源耗费过多的实例,比如Context。因为Context的引用超过它本身的生命周期,会导致Context泄漏。所以尽量使用Application这种Context类型。
3.使用线程池,不要newthread
4.UI视图检查,减少视图层级(hierarchyviewer)。
5.图片优化
6. 重用系统资源:系统定义id,系统图片,系统布局,系统style,系统字符串,系统颜色定义

阅读全文

与androidbitmap内存溢出相关的资料

热点内容
解压文件苹果手机rar 浏览:145
centos开机命令行模式 浏览:695
遍历所有listpython 浏览:660
力控加密文件夹 浏览:515
如何更改移动服务器密码 浏览:686
苹果8p手机加密 浏览:749
ipad建文件夹怎么弄 浏览:833
iphone13对wap3加密 浏览:555
pdf文件打开失败 浏览:913
dubbo怎么调用不同服务器接口 浏览:40
全能解压王app历史版本 浏览:75
优先队列与拓扑排序算法 浏览:281
pdf转换formacbook 浏览:871
pdf文件内容怎么编辑 浏览:48
134压缩机排气温度多少 浏览:256
unity等待编译后 浏览:806
黑鲨手机锁屏视频在哪个文件夹 浏览:781
wow地图解压后怎么压缩 浏览:823
有pdf却打不开 浏览:462
七星彩软件app怎么下载 浏览:219