Volley's main function is to deal with the network and then obtain the corresponding data from the network. Although there is a cache thread (CacheDispatcher), if there is no corresponding record in the cache, it will still be thrown into the network queue, and the network thread (NetworkDispatcher) will work.
Let's take a look at what NetworkDispatcher does, as shown below:
Public void run () {Process. setThreadPriority (Process. THREAD_PRIORITY_BACKGROUND); Request
Request; while (true) {try {// get a request from the queue. If there is no request, the request = mQueue will be blocked all the time. 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"); // determines whether the request has been canceled. if it is canceled, you do not need to continue if (request. isCanceled () {request. finish ("network-discard-canceled"); continue;} addTrafficStatsTag (request); // call the mNetwork to deal with the network NetworkResponse networkResponse = mNetwork. required mrequest (request); request. addMarker ("network-http-complete"); // if the server returns an unmodified (304) response and the request has sent a response object, you do not need to continue, because if (networkResponse. notModified & request. hasHadResponseDelivered () {request. finish ("not-modified"); continue;} // analyze the Response data and return the Response object Response
Response = request. parseNetworkResponse (networkResponse); request. addMarker ("network-parse-complete"); // Based on the shouldCache field of the request, determine whether the request needs to be cached. If necessary, put the request in mCache. If (request. shouldCache () & response. cacheEntry! = Null) {mCache. put (request. getCacheKey (), response. cacheEntry); request. addMarker ("network-cache-written");} // call mDelivery to return the Response object to the main thread for UI update. Request. markDelivered (); mDelivery. postResponse (request, response);} catch (VolleyError volleyError) {parseAndDeliverNetworkError (request, volleyError); // if an error occurs, mDelivery is called to return the error message to the main thread, prompt} catch (Exception e) {VolleyLog. e (e, "Unhandled exception % s", e. toString (); mDelivery. postError (request, new VolleyError (e ));}}}
NetworkDispatcher mainly does the following:
1) Call the take () method of the mQueue to obtain the request from the queue. If there is no request, the request will be blocked until new requests arrive in the queue.
2) check whether the request has been canceled. If yes, obtain the request again.
3) Call the Network object to send the request to the Network and return a NetworkResponse object.
4) Call the request's pareseNetworkResonse method to parse the NetworkResponse object into a corresponding Response object.
5) determine whether the request needs to be cached. If the request needs to be cached, put the cacheEntry object in its Response into the cached mCache.
6) Call mDelivery to upload the Response object to the main thread for UI update.
In Volley, four network threads are running at the same time by default, and the corresponding cache thread has only one.
From the code above, we can see that the Network thread actually calls the Network object to communicate with the Network. In Volley, the default Network implementation class is the BasicNetwork class.
Next let's take a look at its receivmrequest method:
Public NetworkResponse initiate mrequest (Request
Request) throws VolleyError {... while (true) {HttpResponse httpResponse = null; byte [] responseContents = null; Map
ResponseHeaders = new HashMap
(); Try {// Add the header information Map
Headers = new HashMap
(); AddCacheHeaders (headers, request. getCacheEntry (); httpResponse = mHttpStack. descrimrequest (request, headers); // call the HttpStack object to obtain data from the network StatusLine statusLine = httpResponse. getStatusLine (); int statusCode = statusLine. getStatusCode (); responseHeaders = convertHeaders (httpResponse. getAllHeaders (); // get the status code from the response status line. If it is 304 (not modified), it indicates that the data has been obtained before, and the data in the cache is used directly, construct a NetworkResonse object if (statusCode = HttpSt Atus. SC _NOT_MODIFIED) {return new NetworkResponse (HttpStatus. SC _NOT_MODIFIED, request. getCacheEntry () = null? Null: request. getCacheEntry (). data, responseHeaders, true);} // some responses do not contain content. For example, if the response status code is 204, add an empty byte as the content, which will be processed in a unified manner later. If (httpResponse. getEntity ()! = Null) {responseContents = entityToBytes (httpResponse. getEntity ();} else {// Add 0 byte response as a way of honestly representing a // no-content request. responseContents = new byte [0];}... // some log processing is ignored. Return new NetworkResponse (statusCode, responseContents, responseHeaders, false);}... // some exception handling is ignored here} catch (IOException e) {... if (responseContents! = Null) {networkResponse = new NetworkResponse (statusCode, responseContents, responseHeaders, false); if (statusCode = HttpStatus. SC _UNAUTHORIZED | statusCode = HttpStatus. SC _FORBIDDEN) {attemptRetryOnException ("auth", request, new AuthFailureError (networkResponse); // The reacquire Is performed based on Volley's Retyr mechanism.} Else {throw new ServerError (networkResponse) ;}} else {throw new NetworkError (networkResponse );}}}}
BasicNetwork does the following:
1) Add the header information for cached requests as follows:
private void addCacheHeaders(Map
headers, Cache.Entry entry) { // If there's no cache entry, we're done. if (entry == null) { return; } if (entry.etag != null) { headers.put("If-None-Match", entry.etag); } if (entry.serverDate > 0) { Date refTime = new Date(entry.serverDate); headers.put("If-Modified-Since", DateUtils.formatDate(refTime)); } }
2) Call the HttpStack object to obtain data from the network and return the httpResonse object.
3) return different Response Objects Based on status encoding. For example, 304 (not modified) returns the cached data. If not, reconstructs a NetworkResponse object based on the data in the Response.
4) BasicNetwork implements a Retry Mechanism. If the first attempt fails to be obtained from the network, it will try again by default. If the attempt fails, an Error will be returned. The default implementation class is the DefaultRetryPolicy class.
The NetworkResponse object returned in the Network is parsed by the specific Request (such as ImageRequest and JsonRequest) class in NetworkDispatcher, and then returned to the UI thread.
End!
Introduction to cache threads:
Usage of Volley in Android (6) Understanding CacheDispatcher