android OOM(out of memory)异常的处理

解决Android应用中图片加载引起的OOM异常
本文探讨了Android系统在图片加载处理时遇到内存溢出(OOM)异常的问题,详细介绍了Xutils和lazylist框架如何有效解决大图片加载引起的OOM异常。包括内存缓存策略、内存溢出的常见原因及处理方法,以及通过优化加载图片的方式减少内存消耗,避免应用崩溃。

一、Android系统对图片进行加载处理时,内存的申请情况是根据图片的宽高来决定。
要解决OOM异常,需要对加载的大尺寸的图片进行缩放。


Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/a.jpg");
iv.setImageBitmap(bitmap);


当通过此方法加载大图片的时候,容易出现OOM(out of memory)异常。




二、Xutils加载图片


三、lazylist框架专门解决大图片加载oom异常


1.获取系统给该应用分配了多少可用内存 32
2.32/4 = 8M  作为参照物,拿出四分之一的内存来缓存图片
3.在每次做内存缓存的时候都检查一下内存,跟8对比,如果超过8的话直接移除内存 里的缓存
4.
在加载图片的时候,先从内存中去查找是否有缓存图片。如果有就直接返回。
通过imageview去加载图片,如果没有返回图片,则开启新线程加载图片。




一级缓存:内存缓存
二级缓存:文件缓存,也叫sd卡缓存
三级缓存:网络加载图片




四、
造成oom异常的主要原因就是内存被占用,导致无法运行程序。除了图片加载时会出现oom异常,如果程序中的Activity比较多,也会造成oom。
所以,可以将Activity使用fragment代替,或者降低引用级别。





OOM异常的原因和处理
原因:
加载的图片太多或图片过大时经常出现OOM问题
通常OOM都发生在需要用到大量内存的情况下(创建或解析Bitmap,分配特大的数组等)
在GridView或ListView中,数据量有5000,每一屏只显示20个元素,把可见的bitmap保存在内存中,那些不可见的,就释放掉,当元素滑动时,再去加载Bitmap
加载图片的优化:
1、始终从cache中去取Bitmap,如果取到Bitmap,就直接把这个Bitmap设置到ImageView上面。
        2、如果缓存中不存在,那么启动一个task去加载(可能从文件来,也可能从网络)。
        3、每一个ImageView上面都可能绑定一个task,所以,这个ImageView必须提供一个方法能得到与之相关联的task,为什么要这样做?
因为在给一个ImageView绑定task之前,必须要把原先的task取消。


内存溢出的问题:
1.在内存引用上做些处理,比如说使用软引用,强化引用,弱引用
2.可以在内存中加载图片的时候直接在内存中做处理,比如:边界的压缩
3.动态的回收内存
4.优化Dalvik虚拟机的堆内存的分配
5.自定义堆内存大小





### 解决 Android 应用中的 OOM (Out Of Memory) 错误 #### 调整 Gradle 配置增加 JVM 堆大小 对于由 Java 编译过程引起的 OOM 问题,可以通过调整 `gradle.properties` 文件来增大编译时使用的堆内存。具体做法是在项目的 gradle 属性文件中加入以下配置: ```properties org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=4g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 ``` 这将允许更大的堆空间用于构建过程,并在发生 OOM 时自动生成堆转储文件以便分析[^3]。 #### 控制 Bitmap 的加载方式以减少内存消耗 针对由于处理大型图像而导致的 OOM 问题,建议优化图片资源管理策略。例如,在加载位图之前先计算合适的采样率,从而减小编码后的尺寸;或者利用第三方库如 Glide 或 Picasso 来高效地异步加载并缓存网络上的图片。此外,及时回收不再需要的大对象也是很重要的措施之一[^4]。 #### 合理规划应用生命周期内的上下文使用防止泄露 为了避免因不当持有 Activity 实例造成的潜在内存泄漏风险,应当尽可能传递 Application Context 给那些不需要访问 UI 元素的服务组件或其他长时间存活的对象实例。这样不仅可以降低不必要的引用链长度,还能有效预防某些特定场景下发生的循环依赖关系所引发的记忆体无法释放的情况[^5]。 #### 查询当前进程可用 Heap 大小作为参考依据 开发人员还可以通过编程手段获取目标设备上分配给应用程序的最大堆容量,以此为基础制定更合理的内存预算计划。下面是一段用来查询该数值的方法实现代码片段: ```java // 获取Heap Size阈值 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); int memoryClass = am.getMemoryClass(); Log.d("MemoryInfo", "The maximum heap size is:" + String.valueOf(memoryClass)); ``` 此函数返回的结果是以 MB 计算的应用程序所能获得的最大内存量,这对于评估现有架构是否合理以及指导后续性能改进工作具有重要意义[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值