在使用imageloader的过程中如果一个activity里面有较多图片加载,当我们来回切换这个activity时,就会造成内存溢出。在网上查了一点资料,根据别人解析的源码发现 当activity finish时,持有的bitmap没有被释放掉,所以来回多次切换这个activity就会造成内存溢出。而imageloader有个监听会回调返回一个加载生成的bitmap,当我们在onDestory时把bitmap释放掉就会很大程度上释放内存,不至于只切换几次就造成内存溢出。
下面贴出关键代码
public void BaseActivity extends Activity implements ImageLoadingListener{ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //为ImageLoader添加监听 ImageLoader.getInstance().setDefaultLoadingListener(this); } protected void onDestory(){ super.onDestroy(); //释放内存 ImageLoader.getInstance().clearDiskCache(); ImageLoader.getInstance().clearMemoryCache(); //释放被持有的bitmap if(mBitmaps!=null){ for(Bitmap bitmap:mBitmaps){ if(bitmap!=null&&!bitmap.isRecycled()){ bitmap.recycle(); } } } } @Override public void onLoadingCancelled(String s, View view) { } private List<Bitmap>mBitmaps; @Override public void onLoadingComplete(String s, View view, Bitmap bitmap) { if(mBitmaps==null){ mBitmaps=new ArrayList<>(); } mBitmaps.add(bitmap); } @Override public void onLoadingFailed(String s, View view, FailReason failReason) { } @Override public void onLoadingStarted(String s, View view) { } }
这些是处理被持有bitmap的释放,由于imageloader不知道用户需要在什么地方释放,所以需要用户手动添加监听。
下面贴出我再BaseApplication里面Imageloader 的配置 ,与上面的配合使用起来还不错
@Override public void onCreate() { //这是BaseApplication里的 File fileCache = StorageUtils.getCacheDirectory(getApplicationContext()); ImageLoaderConfig.initImageLoader(getApplicationContext(), fileCache); }
/** * Imageloader的配置 * * @author yuLook * */ public class ImageLoaderConfig { /** * 返回默认的参数配置 * * @param isShowDefault * true:显示默认的加载图片 false:不显示默认的加载图片 * @return */ @SuppressWarnings("deprecation") public static DisplayImageOptions initDisplayOptions(boolean isShowDefault) { DisplayImageOptions.Builder displayBuilder = new DisplayImageOptions.Builder(); // 设置图片压缩方式 // EXACTLY: 图像将完全按比例缩小的目标大小 // EXACTLY_STRETCHED: 图片会缩放到目标大小 // IN_SAMPLE_INT: 图像将被二次采样的整数倍 // IN_SAMPLE_POWER_OF_2: 图片将降低2倍,直到下一减少步骤,使图像更小的目标大小 // NONE: 图片不会调整 displayBuilder.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2); if (isShowDefault) { // 默认显示图图片 displayBuilder.showStubImage(R.mipmap.grey_logo); // 地址为空的默认显示图片 displayBuilder.showImageForEmptyUri(R.mipmap.grey_logo); // 加载失败的显示图片 displayBuilder.showImageOnFail(R.mipmap.grey_logo); displayBuilder.showImageOnLoading(R.mipmap.grey_logo); } // 开启内存缓存 displayBuilder.cacheInMemory(true); // 开启SDCard缓存 displayBuilder.cacheOnDisk(true); // 设置图片的编码格式RGB_565, 此格式比ARGB_8888快 displayBuilder.bitmapConfig(Bitmap.Config.RGB_565); displayBuilder.displayer(new FadeInBitmapDisplayer(1000)); return displayBuilder.build(); } public static void initImageLoader(Context context, File cacheFile) { // 获取本地缓存的目录, 该目录在sd卡的根目录 ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder( context); builder.threadPoolSize(2); // 设定线程等级比普通的第一点 builder.threadPriority(Thread.MIN_PRIORITY); // 设定内存为弱缓存 builder.memoryCache(new WeakMemoryCache()); // builder.memoryCache(new ImageMemoryCache(context)); // 设定内存图片缓存大小的限制,不设置默认为屏幕的宽高 builder.memoryCacheExtraOptions(280, 400); builder.memoryCacheSize(10 * 1024 * 1024); // 设定只保存同一尺寸的图片在内存 builder.denyCacheImageMultipleSizesInMemory(); // 设定缓存的SD卡目录,UnlimitDiscCache速度最快 builder.diskCache(new UnlimitedDiskCache(cacheFile)); // 设定网络连接超时timeout:10s 读取网络连接超时read timeout 60s builder.imageDownloader(new BaseImageDownloader(context, 10 * 1000, 60 * 1000)); // 设置ImageLoader的配置参数 builder.defaultDisplayImageOptions(initDisplayOptions(true)); // 初始化imageLoader ImageLoader.getInstance().init(builder.build()); }