Universal Image Loader
简介
Universal Image Loader简称UIL,UIL的目的是提供一个强大,灵活和高度可定制的工具图像加载,缓存和显示。它提供了大量的配置选项,并很好地控制图像加载和缓存的过程
项目地址:https://github.com/nostra13/Android-Universal-Image-Loader
通告
- 真的没有时间开发维护,但无论如何UIL还活着:
- 1.9.4是部署Maven的最新版。项目正在部署到Gradle
新版本变化(1.9.5+)
- 内存缓存重新设计新的
- DisplayImageOptions.targetSize(ImageSize)
- 考虑BitmapFactory.Options.inBitmap
- LruDiskCache中的文件生存时间
特点
- 多线程图像加载(异步或同步)
- ImageLoader有广泛的自定义配置选项(线程执行,下载,解码,内存和磁盘高速缓存,显示图像选择等)
- 每个图像的显示有许多自定义的选项(存根图像,高速缓存交换,解码选项,位图处理,圆角,淡入淡出等)
- 图像加载监听(开始加载,加载完成,加载错误,加载进度)<
安卓2.0+支持
可以加载的文件类型
- “http://site.com/image.png” // http请求返回的图片
- “file:///mnt/sdcard/image.png” // sd卡上的图片
- “file:///mnt/sdcard/video.mp4 // sd卡上的视频缩略图
- “content://media/external/video/media/13”// content 视频缩略图
- “assets://image.png ” // assets目录下的图片
- “drawable://” + R.drawable.img // drawable资源文件
注意:如果是用drawable下的资源文件,建议直接用ImageView.setImageResource(…)样例
样例
//获取ImageLoader实例
ImageLoader imageLoader = ImageLoader.getInstance();
// 加载图片, 编码成Bitmap并显示Bitmap到imageView( 或者显示到任何实现了ImageAware接口的view上 )
imageLoader.displayImage(imageUri, imageView);
// 加载图片, 编码成Bitmap并通过回调返回Bitmap
imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
}
});
// 加载图片,编码成bitmap并返回,此过程同步
Bitmap bmp = imageLoader.loadImageSync(imageUri);
使用
一、Include library
普通
- 下载JAR
- 将包加入项目里面
Maven
<dependency>
<groupId>com.nostra13.universalimageloader</groupId>
<artifactId>universal-image-loader</artifactId>
<version>1.9.4</version>
</dependency>
Gradle
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
二、AndroidMainifest.xml 中添加使用权限
<manifest>
<!-- 从网络下载图片权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 缓存图片到sd卡权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
三、配置
配置DisplayImageOptions
- DisplayImageOptions不是全局的,你可以为每个图像显示配置不同的options。
- 如果没有给imageLoader.displayImage配置 displayimageoptions 那么将使用上面
ImageLoaderconfiguration.defaultdisplayImageOptions()默认的options
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型
/**
BitmapFactory.Options resizeOptions = new BitmapFactory.Options();
resizeOptions.inSampleSize = 3; // decrease size 3 times
resizeOptions.inScaled = true;
*/
.decodingOptions(resizeOptions)//设置图片的解码配置
//.delayBeforeLoading(int delayInMillis)//延时加载
//设置图片加入缓存前,对bitmap进行设置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//设置图片在下载前是否重置
.displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
.build();//构建
- imageScaleType(ImageScaleType imageScaleType)
- EXACTLY :图像将完全按比例缩小的目标大小
- EXACTLY_STRETCHED:图片会缩放到目标大小完全
- IN_SAMPLE_INT:图像将被二次采样的整数倍
- IN_SAMPLE_POWER_OF_2:图片将降低2倍,直到下一减少步骤,使图像更小的目标大小
- NONE:图片不会调整
- displayer(BitmapDisplayer displayer)
- RoundedBitmapDisplayer(int roundPixels)设置圆角图片,180时显示圆形图片
- FakeBitmapDisplayer()这个类什么都没做
- FadeInBitmapDisplayer(int durationMillis)设置图片淡入
- SimpleBitmapDisplayer()正常显示一张图片
配置ImageLoaderConfiguration
- ImageLoaderConfiguration配置是全局的,一个应用里面应该只配置一次。
- ImageLoaderConfiguration配置选项是可选的,你可以只配置其中的一部分。也可以不配置使用默认的。
一般情况使用默认的就可以了
ImageLoaderConfiguration config =ImageLoaderConfiguration.createDefault(getBaseContext());
- 可以选择在Application中初始化设置该类
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(480, 800) // 即保存的每个缓存文件的最大长宽
.discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // Can slow ImageLoader, use it carefully (Better don't use it)/设置缓存的详细信息,最好不要设置这个
.threadPoolSize(3)//线程池内加载的数量
.threadPriority(Thread.NORM_PRIORITY - 2) //优先级
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation/你可以通过自己的内存缓存实现
//内存缓存大小
.memoryCacheSize(2 * 1024 * 1024)
//磁盘缓存大小
.discCacheSize(50 * 1024 * 1024)
/**
1.new Md5FileNameGenerator() 使用MD5对UIL缓存文件进行加密命名
2.new HashCodeFileNameGenerator()使用HASHCODE对UIL缓存文件进行加密命名
*/
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
//File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(),"imageloader/Cache");
.discCache(new UnlimitedDiscCache(cacheDir))
//配置默认的DisplayImageOptions,这个可以在以后使用时再配置。
//1.使用上面配置的config
//2.使用 DisplayImageOptions.createSimple()
//3.不配置
.defaultDisplayImageOptions(config)
// connectTimeout (5 s), readTimeout (30 s)超时时间
.imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000))
// 输出调试信息,发布release版本是去掉
.writeDebugLogs()
//构建
.build();
- 配置好ImageLoaderConfiguration后,调用ImageLoader.getInstance().init(config)初始化;
- 试用中有些属性配置是重复的,我们只要配置其中的一样就可以了,有些或有如下警告,虽然不会直接崩溃,但是看到那么多的黄色警告,怎么能忍?,下面是其中某些警告
- memoryCache() and memoryCacheSize() calls overlap each other
- diskCache(), diskCacheSize() and diskCacheFileCount calls overlap each other
- diskCache() and diskCacheFileNameGenerator() calls overlap each other
三者的关系
ImageLoaderConfiguration是针对图片缓存的全局配置,主要有线程、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。
ImageLoader是具体下载图片,缓存图片,显示图片的具体执行类,它有两个具体的方法displayImage(…)、loadImage(…),但是其实最终他们的实现都是displayImage(…)。
DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理。
四、在Application或者Activity中初始化ImageLoader
- App入口Activity初始化
public class MyActivity extends Activity {
@Override
public void onCreate() {
super.onCreate();
DisplayImageOptions options = DisplayImageOptions.createSimple();
//APP入口Activity配置并初始化,最好放在Application中
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
...
.defaultDisplayImageOptions(options )
...
.build();
ImageLoader.getInstance().init(config);
...
}
}
- Applicaton 初始化(建议此处)
public class BaseApplication extends Application {
private final String TAG = "BaseApplication";
@Override
public void onCreate() {
super.onCreate();
//使用默认配置初始化
ImageLoaderConfiguration config =ImageLoaderConfiguration.createDefault(getBaseContext());
ImageLoader.getInstance().init(config );
}
}
注意:只要初始化一次
五、加载图片
- displayImage 加载的大小按照imageview的大小加载
使用ImageLoaderConfiguration默认options加载
ImageLoader.getInstance().displayImage(uri, imageView);
使用 新建的DisplayImageOptions 加载
ImageLoader.getInstance().displayImage(uri, imageAware, options);
带加载监听
ImageLoader.getInstance().displayImage(uri, imageAware, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String arg0, View arg1) {
// TODO Auto-generated method stub
}
@Override
public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
// TODO Auto-generated method stub
}
@Override
public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
// TODO Auto-generated method stub
}
@Override
public void onLoadingCancelled(String arg0, View arg1) {
// TODO Auto-generated method stub
}
});
loadImage加载同displayImage,不过可以设置加载的bitmap大小,loadImageSync还可以同步加载
加载本地图片
private String SaveBitmap(Bitmap bp) throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir );
bp.compress(Bitmap.CompressFormat.PNG, 90, new FileOutputStream(image));
return image.getAbsolutePath();
}
...
String mCurrentPhotoPath= SaveBitmap(bp);
...
ImageLoader.getInstance().displayImage("file://" + mCurrentPhotoPath, iv_icon, displayImageOptions, new
SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
}
});
使用帮助
- ImageLoader的始终保持图像的纵横比
- 为了避免列表(网格,…)滚动滞后,您可以使用PauseOnScrollListener:
boolean pauseOnScroll = false; // or true
boolean pauseOnFling = true; // or false
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling);
listView.setOnScrollListener(listener);
- 可以使用以下几种磁盘缓存(ImageLoaderConfiguration.diskCache(…))
- UnlimitedDiscCache 默认值,最快的缓存,没有大小限制
- LruDiskCache 缓存受限于总缓存大小和缓存文件数。如果缓存文件超过规定的限制,则最近最少使用的缓存文件将被删除
- LimitedAgeDiscCache 大小无限制的缓存,但是缓存文件有寿命。如果缓存文件的寿命超过规定的限值,然后它会从缓存中被删除
NOTE: UnlimitedDiscCache 比其他的缓存要快
- 可以使用以下几种内存缓存(ImageLoaderConfiguration.memoryCache(…))
- LruMemoryCache 默认的,当超出缓存大小限制最近最少使用的位图被删除
- UsingFreqLimitedMemoryCache 当超出缓存大小限制最不常用的位图被删除
- LRULimitedMemoryCache 当超出缓存大小限制最近最少使用位图被删除
- FIFOLimitedMemoryCache 当超出缓存大小限制,用FIFO规则删除
- LargestLimitedMemoryCache 当超出缓存大小限制最大的位图被删除
- LimitedAgeMemoryCache 当缓存寿命超过规定值,对象将被删除
- WeakMemoryCache 无限缓存
- 如果使用Universal Image Loader 经常出现OutOfMemoryError 错误
- 关闭内存缓存(.cacheInMemory(false)),如果还是出现OOM,那么是你设备的内存太小了,使用MemoryAnalyzer 检测以下,要不然尝试以下步骤:
- 减少线程池的大小(.threadPoolSize(…)),一般是1-5
- display options使用.bitmapConfig(Bitmap.Config.RGB_565) ,RGB_565比ARGB_8888少占用2倍的内存
- 使用 .imageScaleType(ImageScaleType.EXACTLY)
- 使用.diskCacheExtraOptions(480, 320, null)
- UIL是如何决定imageview里面Bitmap大小的?它通常会搜寻以下参数
- ImageView实际的高度和宽度
- 获取android:layout_width 和android:layout_height 参数
- 获取android:maxWidth 和 android:maxHeight 参数
- 获取configuration(memoryCacheExtraOptions(int, int)) 里高度和宽度的 最大值
- 获取屏幕的高度和宽度
- 如果启用了磁盘缓存,然后UIL尝试在外部存储缓存图片(/sdcard/Android/data/[package_name]/cache),如果外部存储设备不可用,则图像的缓存设备上的文件系统。要在外部存储(SD卡)提供缓存添加以下权限的AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />