但是今天突然遇到一些奇怪的问题,当listview每一个item中的图片都使用volley下载时,会出现图片显示乱序的问题,纠结了好久,经过不断的调试,终于找到了问题,与大家分享一下!
使用volley框架,下载图片最主要的部分肯定是ImageLoader,而问题也就出在这里。请看下面这段代码:
- public ImageContainer get(ImageView imgView, String requestUrl, 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, imgView);
- imageListener.onResponse(container, true);
- return container;
- }
- // The bitmap did not exist in the cache, fetch it!
- ImageContainer imageContainer =
- new ImageContainer(null, requestUrl, cacheKey, imageListener, imgView);
- // 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;
- }
- // 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, response);
- }
- }, maxWidth, maxHeight,
- Config.RGB_565, new ErrorListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- onGetImageError(cacheKey, error);
- }
- });
- mRequestQueue.add(newRequest);
- mInFlightRequests.put(cacheKey,
- new BatchedImageRequest(newRequest, imageContainer));
- return imageContainer;
- }
首先,这段代码的意思是check缓存中是否有你想要的图片的url地址,如果有,直接在缓存中取,缓存中如果没有,将创建新的请求(newRequest),并加入到mInFlightRequests这个请求hasmap中, 大家仔细看,你会在上面代码中找到这样一段:
- <span style="white-space:pre"> </span>// 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;
- }
它的意思是检测mInFlightRequests这个请求hasmap中是否已经包含你想要下载的图片,如果有,将这个请求加入到批量处理的请求(BatchedImageRequest)中, 为什么要这样做?其实volley是想帮你解决这样一种情况:假如有2个地方都需要下载同样的图片,而这张图片并没有下载完成(也就是说没办法去缓存中取图片数据),那么volley就会把这两个请求都保存起来,当下载完成后,统一返回给这2个请求的view,这样就不需要下载2遍重复的请求。
那么问题来了,listview图片乱序和这里有什么关系呢? listview控件一直存在这样一个问题:当你没有对listview的高度做设置时,listview就会将每个item都调用2遍getView(有时甚至更多次)。如果你的下载过程写在getview中,每个item就会被执行2次下载过程, 也就是说,上面的这段代码将被执行2次,所以,如果你debug,你会发现你上一次保存的view居然神奇的都变成了listview中第一个item的view,那么每次下载完图片,你就会看到图片乱序了。
修改方法,请看下面代码:
- // 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);
- //由于list显示图片出现乱序问题,因为list会设置2遍,而第一遍加载的所有view都是第一个view(可以通过id看出),所以会出现第一个view不停的换图片的问题,解决方法,将add改为修改原始值
- request.clean();
- request.addContainer(imageContainer);
- return imageContainer;
- }