深入剖析Android的Volley框架中的图片加载功能

2019-12-10 18:25:44于丽

这里首先将请求加入mCurrentRequests,这个mCurrentRequests保存了所有需要处理的Request,主要为了提供cancel的入口。

如果该请求不应该被缓存则直接加入mNetworkQueue,然后返回。

然后判断该请求是否有相同的请求正在被处理,如果有则加入mWaitingRequests;如果没有,则 
加入mWaitingRequests.put(cacheKey, null)和mCacheQueue.add(request)。

ok,到这里我们就分析完成了直观的代码,但是你可能会觉得,那么到底是在哪里触发的网络请求,加载图片呢?

那么,首先你应该知道,我们需要加载图片的时候,会makeImageRequest然后将这个请求加入到各种队列,主要包含mCurrentRequests、mCacheQueue。

然后,还记得我们初始化RequestQueue的时候,启动了几个转发线程吗?CacheDispatcher和NetworkDispatcher。

其实,网络请求就是在这几个线程中真正去加载的,我们分别看一下;

(四)CacheDispatcher

看一眼构造方法;

#CacheDispatcher
 public CacheDispatcher(
      BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue,
      Cache cache, ResponseDelivery delivery) {
    mCacheQueue = cacheQueue;
    mNetworkQueue = networkQueue;
    mCache = cache;
    mDelivery = delivery;
  }

 

这是一个线程,那么主要的代码肯定在run里面。

#CacheDispatcher

 @Override
  public void run() {
    if (DEBUG) VolleyLog.v("start new dispatcher");
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

    // Make a blocking call to initialize the cache.
    mCache.initialize();

    while (true) {
      try {
        // Get a request from the cache triage queue, blocking until
        // at least one is available.
        final Request<?> request = mCacheQueue.take();
        request.addMarker("cache-queue-take");

        // If the request has been canceled, don't bother dispatching it.
        if (request.isCanceled()) {
          request.finish("cache-discard-canceled");
          continue;
        }

        // Attempt to retrieve this item from cache.
        Cache.Entry entry = mCache.get(request.getCacheKey());
        if (entry == null) {
          request.addMarker("cache-miss");
          // Cache miss; send off to the network dispatcher.
          mNetworkQueue.put(request);
          continue;
        }

        // If it is completely expired, just send it to the network.
        if (entry.isExpired()) {
          request.addMarker("cache-hit-expired");
          request.setCacheEntry(entry);
          mNetworkQueue.put(request);
          continue;
        }

        // We have a cache hit; parse its data for delivery back to the request.
        request.addMarker("cache-hit");
        Response<?> response = request.parseNetworkResponse(
            new NetworkResponse(entry.data, entry.responseHeaders));
        request.addMarker("cache-hit-parsed");

        if (!entry.refreshNeeded()) {
          // Completely unexpired cache hit. Just deliver the response.
          mDelivery.postResponse(request, response);
        } else {
          // Soft-expired cache hit. We can deliver the cached response,
          // but we need to also send the request to the network for
          // refreshing.
          request.addMarker("cache-hit-refresh-needed");
          request.setCacheEntry(entry);

          // Mark the response as intermediate.
          response.intermediate = true;

          // Post the intermediate response back to the user and have
          // the delivery then forward the request along to the network.
          mDelivery.postResponse(request, response, new Runnable() {
            @Override
            public void run() {
              try {
                mNetworkQueue.put(request);
              } catch (InterruptedException e) {
                // Not much we can do about this.
              }
            }
          });
        }

      } catch (InterruptedException e) {
        // We may have been interrupted because it was time to quit.
        if (mQuit) {
          return;
        }
        continue;
      }
    }
  }