1 产生原因
OOM 异常是 Android 中经常遇到的一个问题,程序员稍微不注意可能就导致其产生。因为 Android 的每一个应用都是一个 Davlik 虚拟机,该虚拟机的默认堆内存只有 16M ,远远无法跟我们的 PC 机比较,因此很容易导致 OOM(Out Of Memory)异常的产生。
导致这样的异常主要有以下原因:
1、加载大图片或数量过多的图片,因为图片是超级耗内存的;
2、操作数据库的时候 Cursor 忘记关闭;
3、资源未释放,比如 io 流,file 等,
4、内存泄露。
我们常见的 OOM 主要是加载图片导致的。因为后面的三种原因都是可以通过约束程序员的编码规范来进行预防,或者使用性能分析工具来检查。
2 解决方案
图片的处理主要用两种方式。我们的应用中有两处用到了图片。
1 情形一
1 单个文件小,数量大
一个是 ListView 中展示的图片缩略图,这种情况的特点是数量大,但是单个图片内存小,只有几 kb,
2 解决方案
一是图片的缓存策略;
二是 ListView 的优化;
三是 WeakReference(弱引用)的使用。
2 情形二
1 单个文件大
另外一种是大图片,就是用户通过手机拍摄的图片,然后通过 http 的 post 提交的方式提交到服务器上。然后在客户端将这个大图片也展示出来。
2 解决方案
我们主要是首先通过BitmapFactory.Options 参数获取图片的宽和高,然后再根据我们ImageView 的宽高对图片进行一个很大比例压缩。
3 针对情形一的补充
1 WeakReference的使用
WeakReference 是一个类,在 ArrayList 中我们把这个类作为对象传递进去,把我们的图片放在 WeakReference 里面,这样当 davlik 虚拟机内存不够用的时候,就会把 WeakReference 对象回收掉,这样我们在 WeakReference 里面保存的数据也被回收了。
List<WeakReference<Bitmap>>list=new ArrayList<>();
2 关于ListView优化
使用 ConvertView 可以实现对 view 的复用,这样大大节约了每次创建对象的时间,提升了 ListView 的显示效率。
使用 ViewHolder 作为内部类,可以将 view 的子控件封装在 ViewHolder 类中,然后通过View.setTag(ViewHolder)将 view 和 ViewHolder 进行绑定,这样我们就不用每次都调用 view 的 findViewById(id)方法来查找控件。
分页加载。
缓存策略。
使用 ConvertView 解决了一大部分问题,使用 ViewHolder 实现了控件换时间的问题,因为给 View 对象设置一个 Tag 本身就是占用内存的,因此 ViewHolder 的使用还是需要区分不同的应用场景的, 没有绝对的好与不好。如果内存足够
需要高效则 ViewHolder 建议使用,否则不建议使用。view.inflate比view.findViewById更耗时,因为前者完成的功能是把 xml 布局文件通过 pullParser 的形式给解析到内存中,需要 io,需要递归子节点。
520





