0
  1. 首先,我需要说明一下,最近几天我利用空闲时间一直在研究Volley源码,并且已经在github上创建了项目,所以该问题并不是小白问题。项目地址:https://github.com/wangzhengyi/Volley

  2. 这里我提的问题就是ImageLoader类里batchResponse方法的实现问题。

  3. 问题具体描述如下:

我很奇怪,为什么ImageLoader类里面要有一个HashMap来保存BatchedImageRequest集合呢?

    private final HashMap<String, BatchedImageRequest> mBatchedResponses =
            new HashMap<String, BatchedImageRequest>();

毕竟batchResponse是在特定的ImageRequest执行成功的回调中被调用的,调用代码如下:

    protected void onGetImageSuccess(String cacheKey, Bitmap response) {
        // 增加L1缓存的键值对.
        mCache.putBitmap(cacheKey, response);

        // 同一时间内最初的ImageRequest执行成功后,回调这段时间阻塞的相同ImageRequest对应的成功回调接口.
        BatchedImageRequest request = mInFlightRequests.remove(cacheKey);
        if (request != null) {
            request.mResponseBitmap = response;
            // 将阻塞的ImageRequest进行结果分发.
            batchResponse(cacheKey, request);
        }
    }

从上述代码可以看出,ImageRequest请求成功后,已经从mInFlightRequests中获取了对应的BatchedImageRequest对象.而同一时间被阻塞的相同的ImageRequest对应的ImageContainer都在BatchedImageRequest的mContainers集合中.
那我认为,batchResponse方法只需要遍历对应BatchedImageRequest的mContainers集合即可.
但是,ImageLoader源码中,我认为多余的构造了一个HashMap对象mBatchedResponses来保存BatchedImageRequest集合,然后在batchResponse方法中又对集合进行两层for循环各种遍历,实在是非常诡异,求指导.
诡异代码如下:

    private void batchResponse(String cacheKey, BatchedImageRequest request) {
        mBatchedResponses.put(cacheKey, request);
        if (mRunnable == null) {
            mRunnable = new Runnable() {
                @Override
                public void run() {
                    for (BatchedImageRequest bir :  mBatchedResponses.values()) {
                        for (ImageContainer container : bir.mContainers) {
                            if (container.mListener == null) {
                                continue;
                            }

                            if (bir.getError() == null) {
                                container.mBitmap = bir.mResponseBitmap;
                                container.mListener.onResponse(container, false);
                            } else {
                                container.mListener.onErrorResponse(bir.getError());
                            }
                        }
                    }
                    mBatchedResponses.clear();
                    mRunnable = null;
                }
            };
            // Post the runnable
            mHandler.postDelayed(mRunnable, 100);
        }
    }

我认为的代码实现应该是:

    private void batchResponse(String cacheKey, BatchedImageRequest request) {
        if (mRunnable == null) {
            mRunnable = new Runnable() {
                @Override
                public void run() {
                    for (ImageContainer container : request.mContainers) {
                        if (container.mListener == null) {
                            continue;
                        }

                        if (request.getError() == null) {
                            container.mBitmap = request.mResponseBitmap;
                            container.mListener.onResponse(container, false);
                        } else {
                            container.mListener.onErrorResponse(request.getError());
                        }
                    }
                    mRunnable = null;
                }
            };
            // Post the runnable
            mHandler.postDelayed(mRunnable, 100);
        }
    }

撰写答案