Universal Image Loader

UIL_Universal Image Loader

1. Setup

Maven dependency:

1
2
3
4
5
6
7
8
<dependency>
<groupId>com.nostra13.universalimageloader</groupId>
<artifactId>universal-image-loader</artifactId>
<version>1.9.4</version>
</dependency>
Gradle dependency:
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'

Manifest:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<manifest>
<!-- 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" />
...
</manifest>
Usage:
public class MyActivity extends Activity {
@Override
public void onCreate() {
super.onCreate();
// Create global configuration and initialize ImageLoader with this config
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
...
.build();
ImageLoader.getInstance().init(config);
...
}
}

2. Configuration

ImageLoaderConfiguration是全局的,只需要设置一次,可根据需要设置必要选项。

File cacheDir = StorageUtils.getCacheDirectory(context);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(480, 800) // default = device screen dimensions
.diskCacheExtraOptions(480, 800, null)
.taskExecutor(...)
.taskExecutorForCachedImages(...)
.threadPoolSize(3) // default
.threadPriority(Thread.NORM_PRIORITY - 2) // default
.tasksProcessingOrder(QueueProcessingType.FIFO) // default
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new LruMemoryCache(2 1024 1024))
.memoryCacheSize(2 1024 1024)
.memoryCacheSizePercentage(13) // default
.diskCache(new UnlimitedDiskCache(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();

3. Display Options

DisplayImageOptions是局部的,每一进行display的时候都可以不同,需要作为参数传给ImageLoader.displayImage(…)方法。但如果没有进行设置,会采用默认配置,ImageLoaderConfiguration.defaultDisplayImageOptions(…)。
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();

4. Usage

可以接受的URI示例:

1
2
3
4
5
6
7
"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)

使用ImageLoader的方法:

1
2
3
4
5
6
7
8
9
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(imageUri, imageView);
imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
}
});
Bitmap bmp = imageLoader.loadImageSync(imageUri);

load图片,使图片大小变化

1
2
3
4
5
6
7
8
9
ImageSize targetSize = new ImageSize(80, 50); // result Bitmap will be fit to this size
imageLoader.loadImage(imageUri, targetSize, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
}
});
ImageSize targetSize = new ImageSize(80, 50); // result Bitmap will be fit to this size
Bitmap bmp = imageLoader.loadImageSync(imageUri, targetSize, options);

关注load过程的更多的细节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
imageLoader.displayImage(imageUri, imageView, options, 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) {
...
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
...
}
}, new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
...
}
});

Load与Display流程

5. Library Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
ImageLoader |
| - init(ImageLoaderConfiguration)
| - isInited()
| - displayImage(...)
| - loadImage(...)
| - loadImageSync(...)
| - getMemoryCache()
| - clearMemoryCache()
| - getDiskCache()
| - clearDiskCache()
| - denyNetworkDownloads(boolean)
| - handleSlowNetwork(boolean)
| - setDefaultLoadingListener(...)
| - pause()
| - resume()
| - stop()
| - destroy()
| - getLoadingUriForView(ImageView)
| - cancelDisplayTask(ImageView)
ImageAware |
| - getId()
| - getWidth()
| - getHeight()
| - getScaleType()
| - getWrappedView()
| - isCollected()
| - setImageDrawable(Drawable)
| - setImageBitmap(Bitmap)
MemoryCacheUtil |
| - findCachedBitmapsForImageUri(...)
| - findCacheKeysForImageUri(...)
| - removeFromCache(...)
DiskCacheUtil |
| - findInCache(...)
| - removeFromCache(...)
StorageUtils |
| - getCacheDirectory(Context)
| - getIndividualCacheDirectory(Context)
| - getOwnCacheDirectory(Context, String)
ImageScaleType | NONE
| IN_SAMPLE_POWER_OF_2
| IN_SAMPLE_INT
| EXACTLY
| EXACTLY_STRETCHED
QueueProcessingType | FIFO
| LIFO
FailReason.FailType | IO_ERROR
| DECODING_ERROR
| NETWORK_DENIED
| OUT_OF_MEMORY
| UNKNOWN
ImageLoadingListener |
| | - onLoadingStarted(String, View)
| | - onLoadingFailed(String, View, FailReason)
| | - onLoadingComplete(String, View, Bitmap)
| | - onLoadingCancelled(String, View)
|---- SimpleImageLoadingListener
ImageDownloader
|---- BaseImageDownloader
|---- NetworkDeniedImageDownloader
|---- SlowNetworkImageDownloader
ImageDecoder
|---- BaseImageDecoder
BitmapDisplayer
|---- SimpleBitmapDisplayer
|---- FadeInBitmapDisplayer
|---- RoundedBitmapDisplayer
|---- RoundedVignetteBitmapDisplayer
DiskCache
|---- BaseDiscCache
|---- UnlimitedDiscCache
|---- LruDiskCache
|---- LimitedAgeDiscCache
MemoryCacheAware
|---- BaseMemoryCache
| |---- WeakMemoryCache
| |---- LimitedMemoryCache
| |---- UsingFreqLimitedMemoryCache
| |---- LRULimitedMemoryCache
| |---- LargestLimitedMemoryCache
| |---- FIFOLimitedMemoryCache
|---- LimitedAgeMemoryCache
|---- LruMemoryCache
FileNameGenerator
|---- HashCodeFileNameGenerator
|---- Md5FileNameGenerator
PauseOnScrollListener

6. 基本信息

(1.) 默认情况下,在memory或disk上的缓存为disable,需要在DisplayImageOptions中使能,也可以使用下面方法改变默认设置:

1
2
3
4
5
6
7
8
9
10
11
12
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
...
.cacheInMemory(true)
.cacheOnDisk(true)
...
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
...
.defaultDisplayImageOptions(defaultOptions)
...
.build();
ImageLoader.getInstance().init(config);

(2.)如果enable了disk cache,UIL会缓存在外部存储中,路径为/sdcard/Android/data/[package_name]/cache。如果外部存储不可用,则图片会被缓存在设备的文件系统中。需要在Manifest中添加外部存储的访问权限。
(3.)定义Image的大小,UIL会搜索已定义的参数:

1
2
3
4
5
Get actual measured width and height of ImageView
Get android:layout_width and android:layout_height parameters
Get android:maxWidth and/or android:maxHeight parameters
Get maximum width and/or height parameters from configuration (memoryCacheExtraOptions(int, int) option)
Get width and/or height of device screen

(4.)OutOfMemoryError 的处理
(5.)MemoryCache的配置

1
2
3
4
5
6
7
8
9
10
11
12
ImageLoaderConfiguration.memoryCache(...)
Cache using only strong references:
LruMemoryCache (Least recently used bitmap is deleted when cache size limit is exceeded) - Used by default
Caches using weak and strong references:
UsingFreqLimitedMemoryCache (Least frequently used bitmap is deleted when cache size limit is exceeded)
LRULimitedMemoryCache (Least recently used bitmap is deleted when cache size limit is exceeded)
FIFOLimitedMemoryCache (FIFO rule is used for deletion when cache size limit is exceeded)
LargestLimitedMemoryCache (The largest bitmap is deleted when cache size limit is exceeded)
LimitedAgeMemoryCache (Decorator. Cached object is deleted when its age exceeds defined value)
Cache using only weak references:
WeakMemoryCache (Unlimited cache)

(6.)DiskCache的配置ImageLoaderConfiguration.diskCache(…)

1
2
3
UnlimitedDiscCache (The fastest cache, doesn't limit cache size) - Used by default
LruDiskCache (Cache limited by total cache size and/or by file count. If cache size exceeds specified limit then least-recently used file will be deleted)
LimitedAgeDiscCache (Size-unlimited cache with limited files' lifetime. If age of cached file exceeds defined limit then it will be deleted from cache.)

(7.)图片的显示风格,可以设置为圆角和褪色效果

1
2
3
DisplayImageOptions.displayer(...)
RoundedBitmapDisplayer (Displays bitmap with rounded corners)
FadeInBitmapDisplayer (Displays image with "fade in" animation)

(8.)可以设置图片在scrolling时的效果,使用PauseOnScrollListener
(9.)在log中的url后面会后缀图片的大小
(10.)ImageLoader会始终保持宽高比