使用volley框架来加载大量图片时,listView在快速滑动列表时,会发现滑动到列表后面时,图片如果稍微过大,加载会很慢,感觉有很长的等待时间,笔者分析到的原因,volley加载图片的类ImageLoader,虽然做了很多优化,但是在快速滑动列表时,每滑动到一个新的图片加载,就会产生一个新的ImageRequest 进入mRequestQueue请求队列中,后面请求的ImageRequest对象就需要等待前面的ImageRequest请求完毕,才能请求后面的图片。所以有时就会感觉很慢的原因。
笔者对volley的ImageLoader稍微改造了一下 增加一个HashMap<String, String> keymap = new HashMap<String, String>(); 用于记录listView在滑动记录视图ImageView对应的ImageRequest,
修改get方法的参数 String listkey;
public ImageContainer get(String requestUrl, final String listkey,
ImageListener imageListener, int maxWidth, int maxHeight) {
// only fulfill requests that were initiated from the main thread.
throwIfNotOnMainThread();
final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);
// Try to look up the request in the cache of remote images.
Bitmap cachedBitmap = mCache.getBitmap(cacheKey);
if (cachedBitmap != null) {
// Return the cached bitmap.
ImageContainer container = new ImageContainer(cachedBitmap,
requestUrl, null, null, null);
imageListener.onResponse(container, true);
return container;
}
// The bitmap did not exist in the cache, fetch it!
ImageContainer imageContainer = new ImageContainer(null, requestUrl,
cacheKey, imageListener, listkey);
// Update the caller to let them know that they should use the default
// bitmap.
imageListener.onResponse(imageContainer, true);
// Check to see if a request is already in-flight.
BatchedImageRequest request = mInFlightRequests.get(cacheKey);
if (request != null) {
// If it is, add this request to the list of listeners.
request.addContainer(imageContainer);
return imageContainer;
}
//如果加载的imageView的视图有ImageRequest,目前不需要去加载cancel掉,给下一个ImageRequest去加载
if (listkey != null) {
String keyvalue = keymap.get(listkey);
BatchedImageRequest temprequest = mInFlightRequests.get(keyvalue);
if (temprequest != null) {
temprequest.mRequest.cancel();
mInFlightRequests.remove(keyvalue);
keymap.remove(listkey);
}
}
// The request is not already in flight. Send the new request to the
// network and
// track it.
Request<?> newRequest = new ImageRequest(requestUrl,
new Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
onGetImageSuccess(cacheKey, listkey, response);
}
}, maxWidth, maxHeight, Config.RGB_565, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
onGetImageError(cacheKey, listkey,error);
}
});
mRequestQueue.add(newRequest);
mInFlightRequests.put(cacheKey, new BatchedImageRequest(newRequest,
imageContainer));
//如果listkey 不为空保存 BatchedImageRequest的cacheKey
if (listkey != null) {
keymap.put(listkey, cacheKey);
}
return imageContainer;
}
当然在ImageRequest请求加载图片完成后 mInFlightRequests.remove(cacheKey); 要调用 keymap.remove(listkey);
对原有的get方法也要做很多相应的重载,只要有需要列表加载图片时才需要参数listkey
在适配器使用时Listkey的参数使用imageView.hashCode()+"",