android 关于listview bitmap导致的oom解决方案
来源:互联网 发布:淘宝怎么卖游戏币 编辑:程序博客网 时间:2024/06/04 06:20
2015年7月份开始做android项目(之前是做Unix*c和平台研发)。项目是cs模式,使用http post通讯,其中有文章列表,图片是服务器端的,使用listview展示。某一天因为服务器端数据重复,观察app内存使用率时突然发现报oom错误,最后查了一下是bitmap释放不干净,这是异常现场。
观察了一下堆区,在加载新图片时,堆区占用一直持续增长,查了一下发现解释是说 android的bitmap 是一部分用c开辟的,要释放要用bitmap的recyced。因为bitmap没有释放,引用还在被view的imageview抓着,所以每次listview滑动加载新item时都会创建新的view不会循环使用旧的view,当然bitmap也不会释放。这就是导致oom的原因。知道了原因,之后就做了一个三层的缓存(说是三层,实际就2层,我把第1层屏幕正在显示的认为是在显存中)。具体如下:
两层缓存是 内存和本地磁盘,内存存放当前正在显示图片(同时缓存一部分+n 和 -n 位置的图片),磁盘存放已下载的图片。关于内存是做一个队列结构。在适配器的getview和lisview的onscrolled中做以下处理:先查询内存队列中是否有当前item的缓存图片,如果有则使用,如果没有则读取本地图片加载到队列同时将图片bitmap返回,这些处理之后都要做----遍历当前队列缓存,如果当前缓存图片个数超出则释放队列头/尾的bitmap资源,关于释放头还是尾可以根据当前滑动的方向判断。
具体代码demo如下:
/* 适配器中 */
adpter :
/* 队列缓存元素类 @2016.01.22 by djy */
public class cacheItemImg{
/* 元素编号 */
int itemId = null ;
Bitmap itemImag = null ;
public cacheItemImg ( int _id , Bitmap _bit ){
itemId = _id ;
itemImag = _bit ;
}
}
/* 图片缓存队列 用来存储当前需要放在内存中的位图集合 @2016.01.22 by djy */
private List<cacheItemImg> cacheBitCol = new ArryList<cacheItemImg>();
/* 当前队列缓存的元素最大个数 @2016.01.22 by djy*/
private int MAX_CACHE = 5;
/**********************
*
* function : 从缓存中获取指定id的图片位图
*
* item_id :元素编号
* img_path :对应图片的本地路径
*
*********************/
private cacheItemImag getCacheBit(int item_id,string img_path){
/* 清理掉超出缓存个数的图片,默认从队列头部清理,具体使用可以自定 */
/* 如果队列长度超出 */
while( cacheBitCol.size() > MAX_CACHE ){
/* 如果位图已实例化并且未被释放 则释放 */
if( null !=cacheBitCol.get(0).itemImag && !cacheBitCol.get(0).itemImag.isRecyced() ) cacheBitCol.get(0).itemImag.recyced();
/* 从队列清掉刚才释放的头部元素 */
cacheBitCol.Remove(cacheBitCol.get(0));
}
/* 遍历查询当前缓存队列是否存在 指定id的元素 */
foreach( cacheItemImg var : cacheBitCol ){
/* 如果找到 则返回对象 */
if( var.itemId == item_id ) return var;
}
/* 在缓存队列中没有,则从本地加载实例化改位图 */
cacheItemImag tmpCacheItem = new cacheItemImag( item_id , BitmapFactory.decodeStream(new FileInputStream(filePath),null,null) ) ;
/* 将位图加入队列缓存 */
cacheBitCol .Add( tmpCacheItem );
/* 将对象返回 */
return tmpCacheItem;
}
在geview 和 onscrolled中 关键代码: imageview.setBitmap( getCacheBit( viewItem.id , viewItem.imgPath ) );
ps:上述代码没有网络图片, 如果有网络图片,关键在异步,图片下载下来之后,当要设置图片时要先判断当前的 viewItem是否和当前下载的图片匹配。可以在getview时将imagView设置tag为id ,然后在下载完成异步设置图片时 判断当前 imageview tag的id是否一致,一致则设置,不一致则不做工。
上面只是自己实现的一个简单的demo,具体实施的较复杂,但理论是一致的,这个本身很简单,但因不太熟悉android开发及jvm虚拟机这些导致出现的问题。上述方案已经过实施。
- android 关于listview bitmap导致的oom解决方案
- 关于Bitmap 导致的OOM 解决方案
- Bitmap导致的OOM 终极解决方案
- Bitmap导致的OOM 终极解决方案
- Bitmap导致的OOM 一些解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- 关于android 使用bitmap的OOM心得和解决方案
- Android 关于OOM的解决方案
- Android 关于OOM的解决方案
- Android 关于OOM的解决方案
- Android 关于OOM的解决方案
- Android 关于OOM的解决方案
- openstack dashboard实例连接失败的解决办法
- TabPageIndicator ViewPager has not been bound 的异常解决
- phoenixframework自动化平台关于定位信息入库与不入库的示例
- iOS开发笔记--如何自定义启动画面Default.png加载时间
- Android Icons下载使用
- android 关于listview bitmap导致的oom解决方案
- EXTJS 树拖拽和表格拖拽 plugins
- gtk_note
- 从svn上down的项目,在tomcat上部避时摄报错
- 关于Activity中onCreate()方法执行两次的问题
- 用GCC开发STM32,正点原子开发板的一个库函数版本例程示例
- Java设计模式四: 原型模式(Prototype Pattern)
- web页面化工作的前期基础学习(二)——HTML标签属性
- iOS开发笔记--Objective-C中根据函数名调用函数