介绍
先来看下它的特性:
可配置度高。支持任务线程池、下载器、解码器、内存及磁盘缓存、显示选项等等的配置。
包含内存缓存和磁盘缓存两级缓存。
支持多线程,支持异步和同步加载。
支持多种缓存算法、下载进度监听、ListView 图片错乱解决等。
使用
首先需要在Application里面配置它的相关参数并初始化,当然你也可以不用配置直接使用默认配置:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//创建默认的ImageLoader配置参数
ImageLoaderConfiguration configuration = ImageLoaderConfiguration
.createDefault(this);
//使用自定义的参数
ImageLoader.getInstance().init(configuration);
}
}
File cacheDir = StorageUtils.getCacheDirectory(context);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(480, 800) // default = device screen dimensions
.diskCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null)
.taskExecutor(...)
.taskExecutorForCachedImages(...)
.threadPoolSize(3) // default
.threadPriority(Thread.NORM_PRIORITY - 1) // default
.tasksProcessingOrder(QueueProcessingType.FIFO) // default
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new LruMemoryCache(2 * 1024 * 1024))
.memoryCacheSize(2 * 1024 * 1024)
.memoryCacheSizePercentage(13) // default
.diskCache(new UnlimitedDiscCache(cacheDir)) // default
.diskCacheSize(50 * 1024 * 1024)
.diskCacheFileCount(100)
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
.imageDownloader(new BaseImageDownloader(context)) // default
.imageDecoder(new BaseImageDecoder()) // default
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
.writeDebugLogs()
.build();
参数配置里面有很多的可配置项,比如缓存策略、加载线程池大小等,可以根据自己需求配置,这里就不一一讲解了,我们来看下调用方法,框架给我们提供了不止一种的方法来实现加载图片,下面我们来看下几个常用的方法:
loadImage()
final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
ImageLoader.getInstance().loadImage(imageUrl, new ImageLoadingListener() {
@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) {
mImageView.setImageBitmap(loadedImage);
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
}
});
该方法有两个参数,一个是url,一个是ImageLoadingListener,ImageLoadingListener回调方法有4个,图片加载开始,图片加载失败,图片加载完成,图片取消加载,我们可以根据自己的需要在对应的方法写自己的代码。当然如果你不需要这个么多方法,只需要加载完成显示,那可以传一个SimpleImageLoadingListener,他使用的是缺省适配器模式,只需要一个onLoadingComplete方法。
final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
ImageLoader.getInstance().loadImage(imageUrl, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
mImageView.setImageBitmap(loadedImage);
}
});
loadImage还有一个重载方法,可以自定义图片的大小,我们需要自己实例化一个ImageSize对象,设定图片大小传入即可。
final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
ImageSize mImageSize = new ImageSize(100, 100);
ImageLoader.getInstance().loadImage(imageUrl, mImageSize, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
mImageView.setImageBitmap(loadedImage);
}
});
上面是比较简单的用法,我们平时一般需要更复杂的用法。loadImage还有一个重载方法来满足我们的需求,我们可以传入一个DisplayImageOptions来配置一些复杂的参数,比如图片加载之前显示的默认图片,加载失败显示的图片,是否缓存等。
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub) // resource or drawable
.showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable
.showImageOnFail(R.drawable.ic_error) // resource or drawable
.resetViewBeforeLoading(false) // default
.delayBeforeLoading(1000)
.cacheInMemory(false) // default
.cacheOnDisk(false) // default
.preProcessor(...)
.postProcessor(...)
.extraForDownloader(...)
.considerExifParams(false) // default
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
.bitmapConfig(Bitmap.Config.ARGB_8888) // default
.decodingOptions(...)
.displayer(new SimpleBitmapDisplayer()) // default
.handler(new Handler()) // default
.build();
他的用法跟前面的用法一样,直接作为一个参数传入即可,这里就不再贴代码了。
displayImage()
final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
//显示图片的配置
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisk(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
ImageLoader.getInstance().displayImage(imageUrl, mImageView, options);
通过代码可以看到,displayImage方法要简单一点,不需要传入Listener接口,只需要传入url,imageview控件,options即可。这个方法内部会对我们要显示的图片进行剪裁,返回给我们一个大小合适的图片。在图片加载过程中我们有时会需要图片加载的进度,displayImage可以传入一个ImageLoadingProgressListener()来给我们返回进度:
imageLoader.displayImage(imageUrl, mImageView, options, new SimpleImageLoadingListener(), new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current,
int total) {
}
});
除了加载网络图片我们还可以加载本地图片或者是assets,drawable里面的图片,这样的话我们只需要改变一下url就可以的,比如加载本地图片我们首先要知道图片的路径,然后用Scheme.FILE.wrap(path)包装一下即可,相同的assets,drawable,调用Scheme.ASSETS.wrap(path);Scheme.DRAWABLE.wrap(path),看下这个方法的源码:
/** Represents supported schemes(protocols) of URI. Provides convenient methods for work with schemes and URIs. */
public enum Scheme {
HTTP("http"), HTTPS("https"), FILE("file"), CONTENT("content"), ASSETS("assets"), DRAWABLE("drawable"), UNKNOWN("");
private String scheme;
private String uriPrefix;
Scheme(String scheme) {
this.scheme = scheme;
uriPrefix = scheme + "://";
}
其实包装以后的路径添加了对应的:file://。
我们知道在listview,gridview里面的图片加载是比较常用的,我们希望在listvew或girdview滑动的时候不加载图片,等我们停下时候再加载,框架也为我们提供了这样一个监听:
listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));
gridView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));
pauseOnScroll、pauseOnFling是boolean类型的,pauseOnScroll为true代表滑动的时候暂停加载,pauseOnFling为true代表猛的滑动过程停止加载。
缓存策略
框架在缓存处理上做得很到位,它的缓存分两种一种是内存缓存,一种是硬盘缓存,先来看下内存缓存。内存缓存用了LRU least recently used 近期最少使用 算法,也就是说如果缓存空间超过了我们设定的空间大小,那么框架会把近期最少用到的bitmap从缓存移除,存储的结构是基于链表结构的LinkedHashMap。当然自己也可以自定义缓存策略,在初始化配置的时候设置进去。
内存缓存用到了强引用缓存,弱引用缓存还有两者结合的缓存策略。强引用指的是如果创建了一个对象赋给了一个变量,那么这个对象永远不会被垃圾回收机制回收,及时OOM也不会回收,弱引用的对象就会被回收了。
我们来看一下强引用的LruMemoryCache,这个缓存类内部维护的是一个LinkedHashMap,我们为缓存的最大值设置了一个maxsize,缓存图片的时候我们会计算没个图片的大小,根据key判断如果已经缓存了这张照片,那么就把以前的照片移除;如果当前缓存的大小小于maxsize,则不作操作;如果大于maxsize则把第一条数据移除。
硬盘缓存有这样几个类型:
FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)
LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)
TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)
UnlimitedDiscCache(这个缓存类没有任何的限制)
如果上面的几个不符合你的项目需求也可以自定义配置。
关于ImageLoader的学习就到这里,有时间的话看一下源码,可能会有意想不到的收获。