之前写过一篇android异步加载图片类 ,后来接触了一个开源项目universal-image-loader,听说淘宝也是用这玩意

发现自己写的那个异步加载类太简单了,虽然功能是实现了,但是很多优化的问题都没有解决

比如:

同一个ui加载同一张图,会出现只加载一张,其他的加载不了

加载多图的时候会有oom等问题

现在来说说universal-image-loader

多线程图像加载

ImageLoader的高扩展配置(线程池的大小,HTTP选项,内存和光盘高速缓存,显示图像,以及其他)

使用多级缓存存储器和/或设备的文件器系统(或SD卡)

可自定义每个显示的图像调用分隔的选项

Widget支持

Android 1.5以上支持

使用方法:(我自己封装了一个类ImgConfig使用,方便一些)

只需两步即可加载网络图片:

一、初始化

1
ImgConfig.initImageLoader();

二、

1
ImgConfig.showUserSImg(imgUrl, imageview); //图片的url,要显示的view

以下是我自己写的ImgConfig,仅供参考:

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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
public class ImgConfig extends ImageLoader {
private static DisplayImageOptions options_corner;
private static DisplayImageOptions options_square;
private static AnimateFirstDisplayListener animateFirstDisplayListener = new AnimateFirstDisplayListener();

/**
* @param url 服务器的文件名
* @param imageView
* 显示方形图片 S for Square
*/
public static void showUserSImg(String url, ImageView imageView) {
ImageLoader.getInstance().displayImage(url,
imageView, options_square, animateFirstDisplayListener);
}

/**

- @param url 服务器的文件名
- @param imageView
- 圆角 C for Corner
*/
public static void showUserCImg(String url, ImageView imageView) {
ImageLoader.getInstance().displayImage(url,
imageView, options_corner, animateFirstDisplayListener);
}

/**
* 初始化图片读取方式
*/
public static void initImageLoader() {

DisplayImageOptions options_corner = new DisplayImageOptions.Builder()
.showImageOnLoading(ImgHandler.ToCircular(R.drawable.defult_head))
// 加载中
.showImageForEmptyUri(ImgHandler.ToCircular(R.drawable.defult_head))
// 空uri
.showImageOnFail(ImgHandler.ToCircular(R.drawable.defult_head))
// 失败时
.cacheInMemory(true)
// 设置下载的图片是否缓存在内存中
.cacheOnDisc(true)
// 设置下载的图片是否缓存在SD卡中
.considerExifParams(true)
.displayer(new RoundedBitmapDisplayer(10)) // 展现方式:圆角
.resetViewBeforeLoading(true)
.imageScaleType(ImageScaleType.EXACTLY)
// new FadeInBitmapDisplayer(300) 渐现
.build();

options_square = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.defult_head)
.showImageForEmptyUri(R.drawable.defult_head)
.showImageOnFail(R.drawable.defult_head)
.cacheInMemory(true)
.cacheOnDisc(true)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(100)) // 展现方式:渐现
.resetViewBeforeLoading(true)
.imageScaleType(ImageScaleType.EXACTLY)
.build();

// This configuration tuning is custom. You can tune every option, you
// may tune some of them,
// or you can create default configuration by
// ImageLoaderConfiguration.createDefault(this);
// method.
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
ContextUtil.getInstance())
.threadPriority(Thread.NORM_PRIORITY) //线程池的数量
.denyCacheImageMultipleSizesInMemory() // 不同大小图片只有一个缓存,默认多个
.tasksProcessingOrder(QueueProcessingType.LIFO)
// 设置图片下载和显示的工作队列排序
.discCache(new LimitedAgeDiscCache(new File(Constant.SAVE_IMG_PATH),
new Md5FileNameGenerator(), 7 * 24 * 60 * 60)) // 7天自动清除,按秒算
// .writeDebugLogs() // Remove for release app
.imageDownloader( //或许你的服务器有特定的加载图的方式,在这里实现
new BaseImageDownloader(ContextUtil.getInstance()) {
@Override
public InputStream getStream(String imageUri,
Object extra) throws IOException {
return super.getStream(imageUri, extra);
}

@Override
protected InputStream getStreamFromNetwork(
String imageUri, Object extra)
throws IOException {
HttpURLConnection conn = createConnection(
imageUri, extra);

int redirectCount = 0;
while (conn.getResponseCode() / 100 == 3
&& redirectCount < MAX_REDIRECT_COUNT) {
conn = createConnection(
conn.getHeaderField("Location"),
extra);
redirectCount++;
}

InputStream imageStream = null;
try {
imageStream = conn.getInputStream();
} catch (IOException e) {
// Read all data to allow reuse connection
// (http://bit.ly/1ad35PY)
IoUtils.readAndCloseStream(conn
.getErrorStream());
}
return new ContentLengthInputStream(
new BufferedInputStream(imageStream,
BUFFER_SIZE), conn
.getContentLength());
}
}).build();
// Initialize ImageLoader with configuration. 初始化
ImageLoader.getInstance().init(config);
}

/**
* @author Administrator 监听读取完图片
*/
private static class AnimateFirstDisplayListener extends
SimpleImageLoadingListener {
// 放到内存
static final List<String> displayedImages = Collections
.synchronizedList(new LinkedList<String>());

@Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
}

特别提示以下 .disCache() 和 .imageDownloader

因为我不想要自动帮我加密文件,所以我.disCache() 里面的加密方法 new Md5FileNameGenerator()换成了

1
2
3
4
5
6
new FileNameGenerator() {
@Override
public String generate(String imageUri) {
return FileUtil.getFileName(imageUri);
}
}

服务器有自己的加载方式,我把加载.imageDownloader的加载图片方法换了

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
new BaseImageDownloader(ContextUtil.getInstance()) {
@Override
public InputStream getStream(String imageUri,
Object extra) throws IOException {
return super.getStream(imageUri, extra);
}

@Override
protected InputStream getStreamFromNetwork(
String imageUri, Object extra)
throws IOException {
HttpURLConnection conn = createConnection(
imageUri, extra);

int redirectCount = 0;
while (conn.getResponseCode() / 100 == 3
&& redirectCount < MAX_REDIRECT_COUNT) {
conn = createConnection(
conn.getHeaderField("Location"),
extra);
redirectCount++;
}

InputStream imageStream = null;
try {
imageStream = conn.getInputStream();
} catch (IOException e) {
// Read all data to allow reuse connection
// (http://bit.ly/1ad35PY)
IoUtils.readAndCloseStream(conn
.getErrorStream());
}
return new ContentLengthInputStream(
new BufferedInputStream(imageStream,
BUFFER_SIZE), conn
.getContentLength());
}
}

总结:

universal-image-loader 这个开源项目很好用,

研究了源码,有很多启发,扩展性很好,值得学习

官方提供的例子:
universal-image-loader例子