Android imageloader imageLoader.displayImage显图片间长了内存缓慢上升导致溢出
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android imageloader imageLoader.displayImage显图片间长了内存缓慢上升导致溢出相关的知识,希望对你有一定的参考价值。
在listview 中 使用imageLoader.displayImage显示图片 内存不能释放干净,每次加载列表页面都会有1MB左右内存增长,时间长了导致溢出,试了在跳转页面时用
AnimateFirstDisplayListener.displayedImages.clear();
imageLoader.clearMemoryCache();
imageLoader.clearDiscCache();
System.gc();
释放,效果不是很理想,也试过跳转回首页后finish掉其它所有activity,参数配置也换了很多,但也没有解决问题,下面是我的imageloader具体参数配置 ,希望有经验的朋友能给些指点,谢谢。
DisplayImageOptions options = new DisplayImageOptions.Builder().
bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.showStubImage(R.drawable.no_refurbish) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_empty) // 设置图片Uri为空或是错误的时候显示的图片
.cacheInMemory(false) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
.build();
File cacheDir = StorageUtils.getOwnCacheDirectory(context.getApplicationContext(), "imageloader/Cache");
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY-2)
.denyCacheImageMultipleSizesInMemory()
.memoryCacheExtraOptions(150, 150) // default = device screen dimensions
.denyCacheImageMultipleSizesInMemory()
.discCache(new UnlimitedDiscCache(cacheDir))
.discCacheSize(50 * 1024 * 1024)
.memoryCache(new FIFOLimitedMemoryCache(1000000)) // You can pass your own memory cache implementation
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs() // Remove for release app
.defaultDisplayImageOptions(options)
.build();
listview 的getview中 使用
imageLoader.displayImage(imageUrls[position], holder.image);
显示图片
你好 ,我的应用最低支持4.0的 fresco 可以吗,方便提供一个 fresco listview网络加载图片的例子吗,我在网上没有找到
追答这个没什么要求吧,我给你一个网址,有Fresco的使用说明,你自己看看吧,非常简单,比ImageLoader要简单的太多了
注:http://fresco-cn.org/docs/using-drawees-xml.html#_
ImageLoader的使用
使用配置:
1 导入工程jar包:
https://github.com/nostra13/Android-Universal-Image-Loader,找到universal-image-loader-1.9.5.jar
2 写入权限:
3 可导入ImageLoaderUtils进行相关参数配置 :http://download.csdn.net/detail/xiaoleiacm/9535639<!-- Include following permission if you load images from Internet --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Include following permission if you want to cache images on SD card --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
ImageLoader相关:
1 初始化ImageLoaderConfiguration
初始化ImageLoaderConfiguration包括内存缓存设置,SD卡缓存设置,以及下载线程相关设置,进行初始化时需要获取屏幕宽高,以及分配给该应用程序的内存大小(总APP内存的八分一)
/**
* 初始化ImageLoaderConfiguration
*/
private void InitImageLoaderConfiguration() {
/**************** 获得屏幕宽高 start **************************/
DisplayMetrics displayMetrics = new DisplayMetrics();
mContext.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int widthPixels = displayMetrics.widthPixels;
int heightPixels = displayMetrics.heightPixels;
// System.out.println("widthPixels :" + widthPixels + " heightPixels :" + heightPixels);
/*************** 获得屏幕宽高 end ****************************/
/*************** 获取内存缓存的1/8 开始 ************************/
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
/************** 获取内存缓存的1/8 结束 ************************/
/************设置SD卡缓存储存路径 File Dir 开始 ***********************************/
File cacheDirectory = StorageUtils.getOwnCacheDirectory(mContext, "imageloader/Cache");
System.out.println(cacheDirectory); //storage/emulated/legacy/imageloader/Cache
/************设置SD卡缓存储存路径 File Dir 结束 ***********************************/
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(mContext)
/****************************** 内存缓存设置 ****************************/
.memoryCacheExtraOptions(widthPixels, heightPixels) // 屏幕宽高
.memoryCache(new UsingFreqLimitedMemoryCache(cacheSize)) // 可选择不同的内存缓存方式UsingFreqLimitedMemoryCache
.memoryCacheSize(cacheSize)
.denyCacheImageMultipleSizesInMemory() // 拒绝在缓存中缓存多个URL相同的图片
/****************************** 内存缓存设置 ****************************/
/****************************** SD卡缓存设置 ****************************/
.diskCacheExtraOptions(widthPixels, heightPixels, new BitmapProcessor() {
@Override
public Bitmap process(Bitmap bitmap) {
System.out.println("Bitmap :" + bitmap);
return null;
}
}) //储存到SD卡时,对Bitmap进行相应处理,
.diskCache(new UnlimitedDiskCache(cacheDirectory)) //无限制大小缓存 ,同时设置缓存储存路径
.diskCacheSize(50 * 1024 * 1024)// 缓存大小
.diskCacheFileCount(100) //缓存文件数量
.diskCacheFileNameGenerator(new Md5FileNameGenerator()) //对于缓存的图片名进行MD5加密
/****************************** SD卡缓存设置 ****************************/
/****************************** 线程 开始 ****************************/
.threadPoolSize(3)
.threadPoolSize(Thread.NORM_PRIORITY - 2)
.tasksProcessingOrder(QueueProcessingType.LIFO)
/*不需要外部调用,是线程池相关,在ImageLoaderEngine中调用
.taskExecutor()
.taskExecutorForCachedImages()
*/
.defaultDisplayImageOptions(options) // 设置默认图片显示选项 下面的option对象DisplayImageOptions.createSimple()
.imageDownloader(new BaseImageDownloader(mContext, 5 * 1000, 30 * 1000))// connectTimeout (5 s), readTimeout (30 s)超时时间
/****************************** 线程 结束 ****************************/
.build();
ImageLoader.getInstance().init(config);
}
在设置diskCache时 有以下内存缓存可选项:
WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯1不足的地方就是不稳定,缓存的图片容易被回收掉)
2 DisplayImageOptions是进行图片显示的参数,总的包括 图片适配设置,以及显示方式设置
private DisplayImageOptions InitDisplayImageOptions() {
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.mipmap.ic_launcher) //设置在下载期间的图片
.showImageForEmptyUri(R.mipmap.ic_launcher) //
.showImageOnFail(R.mipmap.ic_launcher)
.cacheInMemory(true)
.cacheOnDisk(true)
/************ 图片适配设置 开始************************/
//UIL为了避免将原图放到内存,会根据ImageView的参数来缩小图片的尺寸,这些参数包括
//maxWidth 、maxHeight 、layout_width 、layout_height,另外图片是等比压缩的,为了让图片填满整个view,可以设置ImageView的android:scaleType="fitXY",不过这样如果等比压缩后的图片小于容器的宽和高,会被拉伸变形。
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
/************ 图片适配设置 结束************************/
/********************* 显示方式 开始****************************/
.displayer(new CircleBitmapDisplayer(Color.WHITE, 5))
// .resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new FadeInBitmapDisplayer(5000))
.displayer(new RoundedBitmapDisplayer(100, 5))//是否设置为圆角,弧度为多少
/********************* 显示方式 结束****************************/
.build();
return options;
}
note:返回的option传给了ImageLoaderConfiguration 的defaultDisplayImageOptions(options)
以上配置中的:
1).imageScaleType(ImageScaleType imageScaleType) 是设置 图片的缩放方式
缩放类型mageScaleType:
EXACTLY :图像将完全按比例缩小的目标大小
EXACTLY_STRETCHED:图片会缩放到目标大小完全
IN_SAMPLE_INT:图像将被二次采样的整数倍
IN_SAMPLE_POWER_OF_2:图片将降低2倍,直到下一减少步骤,使图像更小的目标大小
NONE:图片不会调整
2).displayer(BitmapDisplayer displayer) 是设置 图片的显示方式
显示方式displayer:
RoundedBitmapDisplayer(int roundPixels)设置圆角图片
FakeBitmapDisplayer()这个类什么都没做
FadeInBitmapDisplayer(int durationMillis)设置图片渐显的时间
SimpleBitmapDisplayer()正常显示一张图片
之后按照需求调用
3 图片的加载:
1 单独加载1张图片时:
ImageLoader.getInstance().displayImage(imageUrl, imageView); // imageUrl代表图片的URL地址,imageView代表承载图片的IMAGEVIEW控件
ImageLoader.getInstance().displayImage(imageUrl, imageView,options); // imageUrl代表图片的URL地址,imageView代表承载图片的IMAGEVIEW控件 , options代表DisplayImageOptions配置文件
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted() {
//开始加载的时候执行
}
@Override
public void onLoadingFailed(FailReason failReason) {
//加载失败的时候执行
}
@Override
public void onLoadingComplete(Bitmap loadedImage) {
//加载成功的时候执行
}
@Override
public void onLoadingCancelled() {
//加载取消的时候执行
}});
以下是完整的配置Utils,可作为接口调用:
package com.example.admin.myapplication;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.DisplayMetrics;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.display.CircleBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
import com.nostra13.universalimageloader.utils.StorageUtils;
import java.io.File;
/**
* Created by admin on 2016/5/30.
* note:使用步骤 1:初始化ImageLodaerUtils
* 2 调用InitImageLoder
* 3 在进行加载时,调用getOption获得DisplayImageOptions参数
*/
public class ImageLoaderUtils {
private Activity mContext;
public DisplayImageOptions options; // options选项
public ImageLoaderUtils(Activity mContext) {
this.mContext = mContext;
}
/**
* 获取Option设置参数
*
* @return
*/
public DisplayImageOptions getOption() {
return options;
}
/**
* 初始化ImageLodaer
*/
public void InitImageLoder() {
InitDisplayImageOptions();
InitImageLoaderConfiguration();
}
/**
* 初始化DisplayImageOptions
*
* @return
*/
private DisplayImageOptions InitDisplayImageOptions() {
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.mipmap.ic_launcher) //设置在下载期间的图片
.showImageForEmptyUri(R.mipmap.ic_launcher) //
.showImageOnFail(R.mipmap.ic_launcher)
.cacheInMemory(true)
.cacheOnDisk(true)
/************ 图片适配设置 开始************************/
//UIL为了避免将原图放到内存,会根据ImageView的参数来缩小图片的尺寸,这些参数包括
//maxWidth 、maxHeight 、layout_width 、layout_height,另外图片是等比压缩的,为了让图片填满整个view,可以设置ImageView的android:scaleType="fitXY",不过这样如果等比压缩后的图片小于容器的宽和高,会被拉伸变形。
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
/************ 图片适配设置 结束************************/
/********************* 显示方式 开始****************************/
.displayer(new CircleBitmapDisplayer(Color.WHITE, 5))
// .resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new FadeInBitmapDisplayer(5000))
.displayer(new RoundedBitmapDisplayer(100, 5))//是否设置为圆角,弧度为多少
/********************* 显示方式 结束****************************/
.build();
return options;
}
/**
* 初始化ImageLoaderConfiguration
*/
private void InitImageLoaderConfiguration() {
/**************** 获得屏幕宽高 start **************************/
DisplayMetrics displayMetrics = new DisplayMetrics();
mContext.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int widthPixels = displayMetrics.widthPixels;
int heightPixels = displayMetrics.heightPixels;
// System.out.println("widthPixels :" + widthPixels + " heightPixels :" + heightPixels);
/*************** 获得屏幕宽高 end ****************************/
/*************** 获取内存缓存的1/8 开始 ************************/
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
/************** 获取内存缓存的1/8 结束 ************************/
/************设置SD卡缓存储存路径 File Dir 开始 ***********************************/
File cacheDirectory = StorageUtils.getOwnCacheDirectory(mContext, "imageloader/Cache");
System.out.println(cacheDirectory); //storage/emulated/legacy/imageloader/Cache
/************设置SD卡缓存储存路径 File Dir 结束 ***********************************/
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(mContext)
/****************************** 内存缓存设置 ****************************/
.memoryCacheExtraOptions(widthPixels, heightPixels) // 屏幕宽高
.memoryCache(new UsingFreqLimitedMemoryCache(cacheSize)) // 可选择不同的内存缓存方式UsingFreqLimitedMemoryCache
.memoryCacheSize(cacheSize)
.denyCacheImageMultipleSizesInMemory() // 拒绝在缓存中缓存多个URL相同的图片
/****************************** 内存缓存设置 ****************************/
/****************************** SD卡缓存设置 ****************************/
.diskCacheExtraOptions(widthPixels, heightPixels, new BitmapProcessor() {
@Override
public Bitmap process(Bitmap bitmap) {
System.out.println("Bitmap :" + bitmap);
return null;
}
}) //储存到SD卡时,对Bitmap进行相应处理,
.diskCache(new UnlimitedDiskCache(cacheDirectory)) //无限制大小缓存 ,同时设置缓存储存路径
.diskCacheSize(50 * 1024 * 1024)// 缓存大小
.diskCacheFileCount(100) //缓存文件数量
.diskCacheFileNameGenerator(new Md5FileNameGenerator()) //对于缓存的图片名进行MD5加密
/****************************** SD卡缓存设置 ****************************/
/****************************** 线程 开始 ****************************/
.threadPoolSize(3)
.threadPoolSize(Thread.NORM_PRIORITY - 2)
.tasksProcessingOrder(QueueProcessingType.LIFO)
/*不需要外部调用,是线程池相关,在ImageLoaderEngine中调用
.taskExecutor()
.taskExecutorForCachedImages()
*/
.defaultDisplayImageOptions(options) // 设置默认图片显示选项 下面的option对象DisplayImageOptions.createSimple()
.imageDownloader(new BaseImageDownloader(mContext, 5 * 1000, 30 * 1000))// connectTimeout (5 s), readTimeout (30 s)超时时间
/****************************** 线程 结束 ****************************/
.build();
ImageLoader.getInstance().init(config);
}
}
在调用时使用:
imageLoaderUtils = new ImageLoaderUtils(MainActivity.this);
imageLoaderUtils.InitImageLoder();
ImageLoader.getInstance().displayImage(Constants.IMAGES[position], viewHolder.image, imageLoaderUtils.getOption());
Note:
1 UIL会根据layout_height ,layout_width,maxWidth,maxHeight来适配相应图片的大小
How UIL define Bitmap size needed for exact ImageView? It searches defined parameters:
- Get actual measured width and height of ImageView
- Get
android:layout_width
andandroid:layout_height
parameters - Get
android:maxWidth
and/orandroid:maxHeight
parameters - Get maximum width and/or height parameters from configuration (
memoryCacheExtraOptions(int, int)
option) - Get width and/or height of device screen
So try to set android:layout_width
|android:layout_height
orandroid:maxWidth
|android:maxHeight
parameters for ImageView if you know approximate maximum size of it. It will help correctly compute Bitmap size needed for this view and save memory.
2 OOM问题
If you often got OutOfMemoryError in your app using Universal Image Loader then:
- Disable caching in memory. If OOM is still occurs then it seems your app has a memory leak. Use MemoryAnalyzer to detect it. Otherwise try the following steps (all of them or several):
- Reduce thread pool size in configuration (
.threadPoolSize(...)
). 1 - 5 is recommended. - Use
.bitmapConfig(Bitmap.Config.RGB_565)
in display options. Bitmaps in RGB_565 consume 2 times less memory than in ARGB_8888. - Use
.imageScaleType(ImageScaleType.EXACTLY)
- Use
.diskCacheExtraOptions(480, 320, null)
in configuration
3 URL example
"http://site.com/image.png" // from Web
"file:///mnt/sdcard/image.png" // from SD card
"file:///mnt/sdcard/video.mp4" // from SD card (video thumbnail)
"content://media/external/images/media/13" // from content provider
"content://media/external/video/media/13" // from content provider (video thumbnail)
"assets://image.png" // from assets
"drawable://" + R.drawable.img // from drawables (non-9patch images)
以上是关于Android imageloader imageLoader.displayImage显图片间长了内存缓慢上升导致溢出的主要内容,如果未能解决你的问题,请参考以下文章
Android UI-开源框架ImageLoader的完美例子