/** * Creates a new request with the given method. * * @param method the request {@link Method} to use * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ publicStringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener){ super(method, url, errorListener); mListener = listener; } }
publicclassNetworkResponseimplementsSerializable{ /** * @param statusCode the HTTP status code * @param data Response body * @param headers Headers returned with this response, or null for none * @param notModified True if the server returned a 304 and the data was already in cache * @param networkTimeMs Round-trip network time to receive network response */ publicNetworkResponse(int statusCode, byte[] data, Map<String, String> headers, boolean notModified, long networkTimeMs){ this.statusCode = statusCode; this.data = data; this.headers = headers; this.notModified = notModified; this.networkTimeMs = networkTimeMs; } }
publicclassNetworkDispatcherextendsThread{ /** The queue of requests to service. */ privatefinal BlockingQueue<Request<?>> mQueue; /** The network interface for processing requests. */ privatefinal Network mNetwork; /** The cache to write to. */ privatefinal Cache mCache; /** For posting responses and errors. */ privatefinal ResponseDelivery mDelivery; /** Used for telling us to die. */ privatevolatileboolean mQuit = false; }
publicvoidrun(){ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Request<?> request; while (true) { long startTimeMs = SystemClock.elapsedRealtime(); // release previous request object to avoid leaking request object when mQueue is drained. request = null; try { // Take a request from the queue. request = mQueue.take(); } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. if (mQuit) { return; } continue; }
try { request.addMarker("network-queue-take");
// If the request was cancelled already, do not perform the // network request. if (request.isCanceled()) { request.finish("network-discard-cancelled"); continue; }
addTrafficStatsTag(request);
// Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request); request.addMarker("network-http-complete");
// If the server returned 304 AND we delivered a response already, // we're done -- don't deliver a second identical response. if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); continue; }
// Parse the response here on the worker thread. Response<?> response = request.parseNetworkResponse(networkResponse); request.addMarker("network-parse-complete");
// Write to cache if applicable. // TODO: Only update cache metadata instead of entire record for 304s. if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); }
publicExecutorDelivery(final Handler handler){ // Make an Executor that just wraps the handler. mResponsePoster = new Executor() { @Override publicvoidexecute(Runnable command){ handler.post(command); } }; }
handler post 的runnable对象是一个内部类:在 run 方法里调用了Request对象的deliverResponsedeliverErrorfinish方法。
privateclassResponseDeliveryRunnableimplementsRunnable{ privatefinal Request mRequest; privatefinal Response mResponse; privatefinal Runnable mRunnable; publicResponseDeliveryRunnable(Request request, Response response, Runnable runnable){ mRequest = request; mResponse = response; mRunnable = runnable; } @SuppressWarnings("unchecked") @Override publicvoidrun(){ // If this request has canceled, finish it and don't deliver. if (mRequest.isCanceled()) { mRequest.finish("canceled-at-delivery"); return; } // Deliver a normal response or error, depending. if (mResponse.isSuccess()) { mRequest.deliverResponse(mResponse.result); } else { mRequest.deliverError(mResponse.error); } // If this is an intermediate response, add a marker, otherwise we're done // and the request can be finished. if (mResponse.intermediate) { mRequest.addMarker("intermediate-response"); } else { mRequest.finish("done"); } // If we have been provided a post-delivery runnable, run it. if (mRunnable != null) { mRunnable.run(); } } }
// Process requests in the order they are added. request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue"); // If the request is uncacheable, skip the cache queue and go straight to the network. if (!request.shouldCache()) { mNetworkQueue.add(request); return request; } // Insert request into stage if there's already a request with the same cache key in flight. synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); if (mWaitingRequests.containsKey(cacheKey)) { // There is already a request in flight. Queue up. Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey); if (stagedRequests == null) { stagedRequests = new LinkedList<Request<?>>(); } stagedRequests.add(request); mWaitingRequests.put(cacheKey, stagedRequests); if (VolleyLog.DEBUG) { VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey); } } else { // Insert 'null' queue for this cacheKey, indicating there is now a request in // flight. mWaitingRequests.put(cacheKey, null); mCacheQueue.add(request); } return request; }