android Universal-Image-Loader oom:关于bitmap的优化及其他优化
2016-01-29 13:55
381 查看
概述
今天朋友使用Universal-Image-Loader的ImageLoader加载图片时遇到oom的问题,然后我按照网上的方法试了下,都没作用。最后不得不自己定位解决……问题描述
用一个gridview显示网络图片GridView可以下拉刷新(更新最新的20条),上拉加载(加载20条);
当显示100张左右图片的时候,log就会打印出oom异常。
最后定位到是:position相同,但getView()会触发多次(相信很多人都遇到过)。而position相同,获取到网络上图片的bitmap却不是同一对象
加载图片的代码片段
/* *imageUrl 图片地址 *imageView 放图片的ImageView实例 *options 第三方框架的DisplayImageOptions *SimpleImageLoadingListener 图片加载的监听 */ ImageLoader.getInstance().displayImage(imageUrl, imageView, options, new SimpleImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { //getView()调用多次,position相同,但返回的loadedImage对象却是多个实例。 } });
打印的log
01-29 09:11:26.760 ---> android.graphics.Bitmap@2f414b76;position=1 01-29 09:11:26.830 ---> android.graphics.Bitmap@3057b014;position=0 01-29 09:11:26.830 ---> android.graphics.Bitmap@107440bd;position=3 01-29 09:11:26.890 ---> android.graphics.Bitmap@21702bfe;position=6 01-29 09:11:26.950 ---> android.graphics.Bitmap@1810edac;position=9 01-29 09:11:26.950 ---> android.graphics.Bitmap@26a7ca75;position=0 01-29 09:11:26.960 ---> android.graphics.Bitmap@209f0a0a;position=8 01-29 09:11:26.960 ---> android.graphics.Bitmap@2682827b;position=7 01-29 09:11:27.000 ---> android.graphics.Bitmap@caccb57;position=0 01-29 09:11:27.000 ---> android.graphics.Bitmap@27d14644;position=5 01-29 09:11:27.000 ---> android.graphics.Bitmap@141bd32d;position=4 01-29 09:11:27.050 ---> android.graphics.Bitmap@2abe82b0;position=2 01-29 09:11:27.050 ---> android.graphics.Bitmap@30f7529;position=0 01-29 09:11:27.110 ---> android.graphics.Bitmap@179fce4f;po 4000 sition=0 01-29 09:13:05.350 ---> android.graphics.Bitmap@1a5536a4;position=12 01-29 09:13:05.350 ---> android.graphics.Bitmap@13c66c0d;position=0 01-29 09:13:05.350 ---> android.graphics.Bitmap@3f7627c2;position=15 01-29 09:13:05.350 ---> android.graphics.Bitmap@77839d3;position=13 01-29 09:13:05.420 ---> android.graphics.Bitmap@1874ed1a;position=18 01-29 09:13:05.420 ---> android.graphics.Bitmap@623104b;position=19 01-29 09:13:05.420 ---> android.graphics.Bitmap@30e6fa28;position=16 01-29 09:13:05.420 ---> android.graphics.Bitmap@1580e341;position=17 01-29 09:13:05.420 ---> android.graphics.Bitmap@3264c0e6;position=14 01-29 09:13:05.420 ---> android.graphics.Bitmap@3f906627;position=11 01-29 09:13:05.420 ---> android.graphics.Bitmap@38c590d4;position=10 01-29 09:13:05.420 ---> android.graphics.Bitmap@3637727d;position=9 01-29 09:13:05.420 ---> android.graphics.Bitmap@42c0572;position=8 01-29 09:13:05.420 ---> android.graphics.Bitmap@18933dc3;position=0 01-29 09:13:05.420 ---> android.graphics.Bitmap@1b54e640;position=3 01-29 09:13:05.420 ---> android.graphics.Bitmap@16cdb979;position=7 01-29 09:13:05.480 ---> android.graphics.Bitmap@ce13d58;position=0 01-29 09:13:05.480 ---> android.graphics.Bitmap@26a81eb1;position=4 01-29 09:13:05.480 ---> android.graphics.Bitmap@1cd52f96;position=5 01-29 09:13:05.480 ---> android.graphics.Bitmap@1f492717;position=6 01-29 09:13:05.480 ---> android.graphics.Bitmap@2ed8d704;position=2 01-29 09:13:05.480 ---> android.graphics.Bitmap@14eef4ed;position=1
解决方案
gridview->adapter->getView()->使用框架bitmap优化代码片段public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { addRecycleBitmap(position,loadedImage);//复用bitmap对象 }
addRecycleBitmap()方法代码
private HashMap<Integer,Bitmap> recycleBitmaps = new private HashMap<Integer,Bitmap>(); Bitmap localBitmap= null; /** *将不再使用的bitmap recycle掉 */ public void addRecycleBitmap(int position,Bitmap bitmap) { //注意这里不能优化position=0的,否则不显示第一个。原因还要再仔细瞅瞅 if(recycleBitmaps.containsKey(position)&&position!=0){//第1位已经有bitmap了 localBitmap = recycleBitmaps.get(position); if(null != localBitmap&&localBitmap != bitmap&&!localBitmap.isRecycled()){ localBitmap.recycle(); localBitmap = null; } } recycleBitmaps.put(position,bitmap); }
到此,就能解决掉这个问题了。当然代码方面还可以优化,只是说这个问题的解决方案是这样的……只是还有几点疑惑
疑惑
为什么getView()的position=0,bitmap没法recycle同一个position=0为什么执行了多次(知道是因为重新绘制了界面,但是具体代码源码没浏览到)
bitmap所在的activity销毁了,bitmap对象被回收了?
如果图片不停的增加,到1000张甚至更多,这肯定会撑爆。所以最终解决方案就是类似getView的复用
网上一些关于解决ImageLoader OOM的建议
参考博客1. 减少线程池中线程的个数,在ImageLoaderConfiguration中的(.threadPoolSize)中配置,推荐配置1-5
2. 在DisplayImageOptions选项中配置bitmapConfig为Bitmap.Config.RGB_565,因为默认是ARGB_8888, 使用RGB_565会比使用ARGB_8888少消耗2倍的内存
3. 在ImageLoaderConfiguration中配置图片的内存缓存为memoryCache(new WeakMemoryCache()) 或者不使用内存缓存
4. 在DisplayImageOptions选项中设置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScaleType.EXACTLY)
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories