Volley is simple to learn and use 5-source code analysis 3-volley source code analysis

Source: Internet
Author: User

Volley is simple to learn and use 5-source code analysis 3-volley source code analysis

I. Volley workflow:


Ii. NetworkNetwork requests to be processed in NetworkDispatcher are processed as follows:
    NetworkResponse networkResponse = mNetwork.performRequest(request);
Let's take a look at mNetwork definition: (defined in NetworkDispatcher)

    /** The network interface for processing requests. */    private final Network mNetwork;
NetworkDispatcher. mNetwork initialization occurs in RequestQueue. start:

    NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,         mCache, mDelivery);
While RequestQueue. mNetwork is passed in its constructor:

    public RequestQueue(Cache cache, Network network, int threadPoolSize,            ResponseDelivery delivery) {        mCache = cache;        mNetwork = network;        mDispatchers = new NetworkDispatcher[threadPoolSize];        mDelivery = delivery;    }
The build of RequestQueue from the previous analysis is implemented in Volley. newRequestQueue:

// Create a Network object Network = new BasicNetwork (stack) with the stack parameter; // create a RequestQueue object RequestQueue queue = new RequestQueue (new DiskBasedCache (cacheDir), network ); queue. start (); // The next analysis entry

It can be seen that the mNetwork is actually a BasicNetwork object. In NetworkResponse, The mNetwork actually calls BasicNetwork. ipvmrequest (). This is a function specifically used to process network requests. Its function is to call HttpStackProcess the request and convert the result ResponseDeliveryProcessed NetworkResponse. Let's take a look at its source code:
@ Override public NetworkResponse initiate mrequest (Request <?> Request) throws VolleyError {long requestStart = SystemClock. elapsedRealtime (); while (true) {HttpResponse httpResponse = null; byte [] responseContents = null; Map <String, String> responseHeaders = new HashMap <String, String> (); try {/** ignore network processing details * // Gather headers. map <String, String> headers = new HashMap <String, String> (); addCacheHeaders (headers, request. getCacheEntry ();/** execute network Request * called here HttpStack. initiate mrequest and get an HttpResponse returned result */httpResponse = mHttpStack. required mrequest (request, headers); StatusLine statusLine = httpResponse. getStatusLine (); int statusCode = statusLine. getStatusCode (); responseHeaders = convertHeaders (httpResponse. getAllHeaders ();/** freshness verification: * 304 Not Modified: the client has a buffered file and sends a conditional Request * (generally, the If-Modified-Since header is provided, indicating that the customer only wants to update the document on a specified date ). * The server tells the customer that the previously buffered documents can still be used. */If (statusCode = HttpStatus. SC _NOT_MODIFIED) {/** resolved to NetworkResponse, returns */return new NetworkResponse (HttpStatus. SC _NOT_MODIFIED, request. getCacheEntry (). data, responseHeaders, true);} // determine whether responses has entity information. Some responses, such as 204, do not contain content. Therefore, you need to verify if (httpResponse. getEntity ()! = Null) {// convert object information to byte [] responseContents = entityToBytes (httpResponse. getEntity ();} else {// responseContents = new byte [0];} // handle timeout. long requestLifetime = SystemClock. elapsedRealtime ()-requestStart; logSlowRequests (requestLifetime, request, responseContents, statusLine); if (statusCode <200 | statusCode> 299) {throw new IOException ();} return new NetworkResponse (statusCode, responseContents, responseHeaders, false);} catch (SocketTimeoutException e) {attemptRetryOnException ("socket", request, new TimeoutError ();} catch (ConnectTimeoutException e) {attemptRetryOnException ("connection", request, new TimeoutError ();} catch (MalformedURLException e) {throw new RuntimeException ("Bad URL" + request. getUrl (), e);} catch (IOException e ){...}}}

Summarize the work done by Network. receivmrequest:

1. The incoming HttpStack object executes the network request: mHttpStack. ipvmrequest ()

2. parse the response result and parse HttpResponse to NetworkResponse;

3. Verify the freshness of the returned results (304)

4. Convert the object information of response into a byte array

5. Handle timeout. If an error occurs, such as timeout or authentication failure, retry the operation (attemptRetryOnException) until the operation is successful or an exception is thrown (the retry policy is not met.


AttemptRetryOnException () is a request retry operation based on the retry policy:

    /**     * Attempts to prepare the request for a retry. If there are no more attempts remaining in the     * request's retry policy, a timeout exception is thrown.     */    private static void attemptRetryOnException(String logPrefix, Request<?> request,            VolleyError exception) throws VolleyError {        RetryPolicy retryPolicy = request.getRetryPolicy();        int oldTimeout = request.getTimeoutMs();         try {            retryPolicy.retry(exception);        } catch (VolleyError e) {            request.addMarker(                    String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));            throw e;        }        request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));    }
Iii. HttpClientStack and HurlStackAccording to the source code above, the network request processing logic is actually handled by the passed parameter HttpStack. Previously analyzed, Android used HttpClientStack and HurlStack; 1. Check the parent class HttpStack:
Public interface HttpStack {/*** Performs an HTTP request with the given parameters. * <p> a get request is sent if request. getPostBody () = null. a post request is sent otherwise, * and the Content-Type header is set to request. getPostBodyContentType (). </p> * @ param request the request to perform * @ param add an additional Request Headers {@ link request # getHeaders ()} */public HttpResponse response mrequest (Re Quest <?> Request, Map <String, String> additionalHeaders) throws IOException, AuthFailureError ;}
2. HttpClientStack (implemented using HttpClient)

@ Override public HttpResponse initiate mrequest (Request <?> Request, Map <String, String> additionalHeaders) throws IOException, AuthFailureError {HttpUriRequest httpRequest = createHttpRequest (request, authorization); // See Appendix 1 addHeaders (httpRequest, authorization); addHeaders (httpRequest, request. getHeaders (); onPrepareRequest (httpRequest); // Nothing. empty function, used for rewriting. This function is called before the request is excute // some network settings HttpParams httpParams = httpRequest. getParams (); int timeoutMs = request. getTimeoutMs (); // TODO: Reevaluate this connection timeout based on more wide-scale/data collection and possibly different for wifi. 3G. httpConnectionParams. setConnectionTimeout (httpParams, 5000); HttpConnectionParams. setSoTimeout (httpParams, timeoutMs); return mClient.exe cute (httpRequest );}
Appendix 1: createHttpRequest function:

/*** Construct an appropriate HttpUriRequest */static HttpUriRequest createHttpRequest (request <?> Request, Map <String, String> additionalHeaders) throws AuthFailureError {switch (request. getMethod () {case Method. DEPRECATED_GET_OR_POST: {// This is the deprecated way that needs to be handled for backwards compatibility. // If the request's post body is null, then the assumption is that the request is // GET. otherwise, it is assumed that the request is a POST. byte [] postBody = request. getP OstBody (); if (postBody! = Null) {HttpPost postRequest = new HttpPost (request. getUrl (); postRequest. addHeader (HEADER_CONTENT_TYPE, request. getPostBodyContentType (); HttpEntity entity; entity = new ByteArrayEntity (postBody); postRequest. setEntity (entity); return postRequest;} else {return new HttpGet (request. getUrl () ;}}/*********** generally use POST and GET, it is equivalent to the general process of HttpClient ****************/case Method. GET: return new HttpGet (request. getUrl (); case Method. DELETE: return new HttpDelete (request. getUrl (); case Method. POST: {HttpPost postRequest = new HttpPost (request. getUrl (); // here we can see the meaning of rewriting the getBodyContentType () function when the previous Request is implemented. addHeader (HEADER_CONTENT_TYPE, request. getBodyContentType (); setEntityIfNonEmptyBody (postRequest, request); return postRequest;} case Method. PUT: {HttpPut putRequest = new HttpPut (request. getUrl (); putRequest. addHeader (HEADER_CONTENT_TYPE, request. getBodyContentType (); setEntityIfNonEmptyBody (putRequest, request); return putRequest;} default: throw new IllegalStateException ("Unknown request method. ");}}
3. HurlStack (implemented by HttpURLConnection)
@ Override public HttpResponse initiate mrequest (Request <?> Request, Map <String, String> additionalHeaders) throws IOException, AuthFailureError {String url = request. getUrl (); HashMap <String, String> map = new HashMap <String, String> (); map. putAll (request. getHeaders (); map. putAll (additionalHeaders); // For details about UrlRewriter, see if (mUrlRewriter! = Null) {String rewritten = mUrlRewriter. rewriteUrl (url); if (rewritten = null) {thrownew IOException ("URL blocked by rewriter:" + url) ;}url = rewritten ;} *******************/ URL parsedUrl = new URL (url ); httpURLConnection connection = openConnection (parsedUrl, request); for (String headerName: map. keySet () {connection. addRequestProperty (headerName, Map. get (headerName);} setConnectionParametersForRequest (connection, request); // Initialize HttpResponse with data from the HttpURLConnection. protocolVersion protocolVersion = new ProtocolVersion ("HTTP", 1, 1); int responseCode = connection. getResponseCode (); if (responseCode =-1) {//-1 is returned by getResponseCode () if the response code cocould not be retrieved. // Signal to the caller th At something was wrong with the connection. thrownew IOException ("cocould not retrieve response code from HttpUrlConnection. ");} StatusLine responseStatus = new BasicStatusLine (protocolVersion, connection. getResponseCode (), connection. getResponseMessage (); BasicHttpResponse response = new BasicHttpResponse (responseStatus); response. setEntity (entityFromConnection (connection); for (Entry <String, Li St <String> header: connection. getHeaderFields (). entrySet () {if (header. getKey ()! = Null) {Header h = new BasicHeader (header. getKey (), header. getValue (). get (0); response. addHeader (h) ;}} return response ;}
Appendix 1: UrlRewriter

/** Rewrite and convert URLs before use */public interface UrlRewriter {/*** Returns a URL to use instead of the provided one, or null to indicate * this URL shocould not be used at all. */public String rewriteUrl (String originalUrl );}
The mUrlRewriter parameter is passed in through the HTTP stack constructor. Therefore, you can customize it as follows:
    public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {        mUrlRewriter = urlRewriter;        mSslSocketFactory = sslSocketFactory;    }

4. NetworkResponseReturn to the run () function in NetworkDispatcher (Thread), where:

NetworkResponse networkResponse = mNetwork. receivmrequest (request );

Next, let's continue to look at the source code of NetworkResponse: The NetworkResponse class is very simple. It is only used to pass data in multiple classes. Its member variables: 1) member variables int statusCodeHttp response status code

byte[] dataBody Data
Map<String, String> headersResponse Headers
boolean notModifiedIndicates whether the response is 304.
long networkTimeMsRequest duration

2) The subject is only a few constructors:
    public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers,            boolean notModified) {        this.statusCode = statusCode;        this.data = data;        this.headers = headers;        this.notModified = notModified;    }     public NetworkResponse(byte[] data) {        this(HttpStatus.SC_OK, data, Collections.<String, String>emptyMap(), false);    }     public NetworkResponse(byte[] data, Map<String, String> headers) {        this(HttpStatus.SC_OK, data, headers, false);    }
3) review the data transmission relationships between NetworkResponse classes:



The subject here is based on NetworkDispatcher. run () function for analysis 0, the function calls Network. required mrequest (); NetworkResponse networkResponse = mNetwork. initiate mrequest (request); and Network. descrimrequest () is implemented based on HttpStack; 1. HttpClientStack and HurlStack (implemented based on HttpClient and HttpURLConnection respectively). public HttpResponse implements mrequest () function returns HttpResponse; 2. Network (actually BasicNetwork) using the two HttpStack classes in 1, obtain the returned value HttpResponse, and resolve it to NetworkResponse; 3. abstract protected Response <T> parseNetworkResponse (NetworkResponse response) in the Request; resolve NetworkResponse to Response; and the call of this function is called in the run () function of NetworkDispatcher; 4. In NetworkDispatcher. the last step of run (): mDelivery. postResponse (request, response); pass response to ResponseDelivery and continue to look at the Delivery logic;

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.