Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to analyze the source code of HTTP Request in Android Volley library

2025-03-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is to share with you how to Android Volley library HTTP Request part of the source code analysis, the editor feels very practical, so share with you to learn, I hope you can get something after reading this article, say no more, follow the editor to have a look.

Directory tree of directory source code:

[android] ┗━ [volley] ┣━ AuthFailureError.java ┣━ Cache.java ┣━ CacheDispatcher.java ┣━ DefaultRetryPolicy.java ┣━ ExecutorDelivery.java ┣━ InternalUtils.java ┣━ Network.java ┣━ NetworkDispatcher.java ┣━ NetworkError.java ┣━ NetworkResponse.java ┣━ NoConnectionError.java ┣━ ParseError.java ┣━ RedirectError.java ┣━ Request.java ┣━ RequestQueue.java ┣━ Response.java ┣━ ResponseDelivery.java ┣━ RetryPolicy.java ServerError.java TimeoutError.java [toolbox] AndroidAuthenticator.java ┃ ┣━ Authenticator.java ┃ ┣━ BasicNetwork.java ┃ ┣━ ByteArrayPool.java ┃ ┣━ ClearCacheRequest.java ┃ ┣━ DiskBasedCache.java ┃ ┣━ HttpClientStack.java ┃ ┣━ HttpHeaderParser.java ┃ ┣━ HttpStack.java ┃ ┣━ HurlStack.java ┃ ImageLoader.java ImageRequest.java JsonArrayRequest.java JsonObjectRequest.java JsonRequest.java NetworkImageView.java NoCache.java PoolingByteArrayOutputStream .java ┃ ┣━ RequestFuture.java ┃ ┣━ StringRequest.java ┃ ┗━ Volley.java ┣━ VolleyError.java ┗━ VolleyLog.java

As you can see, the Volley source code is cluttered, and the classes of different functional modules are not grouped into different packages. In contrast, the source code structure of UIL is more standardized and reasonable.

Starting with the commonly used case, infer its project architecture

The simplest examples given on the official website are as follows:

Final TextView mTextView = (TextView) findViewById (R.id.text)

/ / 1. Create a new Queue RequestQueue queue = Volley.newRequestQueue (this); String url = "http://www.google.com"; / / 2. Create a new Request and write listener StringRequest stringRequest = new StringRequest (Request.Method.GET, url, new Response.Listener () {@ Override public void onResponse (String response) {/ / Display the first 500characters of the response string. MTextView.setText ("Response is:" + response.substring (0500))}, new Response.ErrorListener () {@ Override public void onErrorResponse (VolleyError error) {mTextView.setText ("That didn't work!");}}); / / 3. Put Request into Queue and execute queue.add (stringRequest); combined with the following diagram: architecture diagram we can get a general idea of how Volley is used (see notes) and its internal structure. The following is a brief description of the source code level of this usecase deployment. The Volley class Volley class provides four static methods to make it easy for users to create a new Queue. Where: public static RequestQueue newRequestQueue (Context context) {return newRequestQueue (context, null);} a sentence will eventually call: / / input context,stack=null,maxDiskCacheBytes=-1 public static RequestQueue newRequestQueue (Context context, HttpStack stack, int maxDiskCacheBytes) {File cacheDir = new File (context.getCacheDir (), DEFAULT_CACHE_DIR); String userAgent = "volley/0"; / / 1. Set userAgent try {String packageName = context.getPackageName (); PackageInfo info = context.getPackageManager (). GetPackageInfo (packageName, 0); userAgent = packageName + "/" + info.versionCode;} catch (NameNotFoundException e) {} if (stack = = null) {if (Build.VERSION.SDK_INT > = 9) {/ / 2. Choose which httpclient stack = new HurlStack ();} else {/ / Prior to Gingerbread, HttpUrlConnection was unreliable. / / See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html stack = new HttpClientStack (AndroidHttpClient.newInstance (userAgent));}} Network network = new BasicNetwork (stack); RequestQueue queue; if (maxDiskCacheBytes = 9) or org.apache.http.client.HttpClient

After the new Queue is created, the Queue will be start immediately.

The stack class is responsible for sending request (com.android.volley.Request) and getting response (org.apache.http.HttpResponse), while the network class is responsible for analyzing and processing response, wrapped as NetworkResponse (com.android.volley.NetworkResponse). Let's first ignore the details related to network and take a look at the implementation of queue and the scheduling strategy of request. RequestQueue first take a look at the construction method of RequestQueue: public RequestQueue (Cache cache, Network network) {this (cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);}

Call:

Public RequestQueue (Cache cache, Network network, int threadPoolSize) {this (cache, network, threadPoolSize, new ExecutorDelivery (new Handler (Looper.getMainLooper ();} A new face ExecutorDelivery appears here, and it can be guessed literally that it is responsible for distributing the result of the request to the main thread or performing a callback (listener) on the main thread. Continue to call: public RequestQueue (Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {mCache = cache; mNetwork = network; mDispatchers = new NetworkDispatcher [threadPoolSize]; mDelivery = delivery;}

Here's a new face, NetworkDispatcher. Noticing the literal meaning of threadPoolSize as an array length parameter, combined with the above Volley architecture diagram, we assume that NetworkDispatcher is a work thread that iteratively waits and executes request on Queue through network.

When RequestQueue is instantiated, its start () method is called:

Public void start () {stop (); / / Make sure any currently running dispatchers are stopped. / / Create the cache dispatcher and start it. MCacheDispatcher = new CacheDispatcher (mCacheQueue, mNetworkQueue, mCache, mDelivery); mCacheDispatcher.start (); / / Create network dispatchers (and corresponding threads) up to the pool size. For (int I = 0; I

< mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } } 相应地有: public void stop() { if (mCacheDispatcher != null) { mCacheDispatcher.quit(); } for (int i = 0; i < mDispatchers.length; i++) { if (mDispatchers[i] != null) { mDispatchers[i].quit(); } } } 这里的逻辑很简单: 开始之前停止所有旧的任务(即interrupt所有worker thread)。 启动一个负责cache的worker thread。 启动n个负责network的worker thread。 worker thread开始不断地等待来自Queue的request。 Request 接下来执行queue.add(stringRequest); ,一个request被加入到queue中,代码如下所示: public Request add(Request request) { // Tag the request as belonging to this queue and add it to the set of current requests. request.setRequestQueue(this); synchronized (mCurrentRequests) { mCurrentRequests.add(request); } // Process requests in the order they are added. request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue"); // marker用来指示request当前的状态,实际上是用来打log // 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>

();} 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;}}

The logic here is:

Make some settings for the newly added request.

If you don't need cache, add request directly to network queue.

Check whether the request is executing according to key. If so, put it into the waiting linked list. Guess that when the request is complete, a method will be called to remove the key from the waiting linked list, and then execute the request of the waiting in turn. If not, add it to the cache queue.

CacheDispatcher

Assuming that the uri access is executed for * times, the corresponding request will be put into the cache queue. Cache worker thread (cache dispatcher) discovers the existence of request in cache queue and immediately dequeue it and executes it. Let's take a look at CacheDispatcher's run method:

Public class CacheDispatcher extends Thread {private final Cache mCache; / / initially passed in "new DiskBasedCache (cacheDir)". Public void quit () {mQuit = true; interrupt ();} @ 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 (); Request request; while (true) {/ / release previous request object to avoid leaking request object when mQueue is drained. Request = null; / / ensure that the memory can be reclaimed in time after the completion of a request. Try {/ / Take a request from the queue. Request = mCacheQueue.take (); / / blocking} catch (InterruptedException e) {/ / We may have been interrupted because it was time to quit. If (mQuit) {return; / / exit point} continue;} try {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;} / / miss cache puts request directly into network queue 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;} / / cache expires, put request directly into network queue if (entry.isExpired ()) {request.addMarker ("cache-hit-expired"); request.setCacheEntry (entry); mNetworkQueue.put (request); continue;} / / package data in cache into a response request.addMarker ("cache-hit"); Response response = request.parseNetworkResponse (new NetworkResponse (entry.data, entry.responseHeaders)); request.addMarker ("cache-hit-parsed") If (! entry.refreshNeeded ()) {/ / cache does not need to be refreshed, just hand over the response to delivery mDelivery.postResponse (request, response);} else {/ / cache needs to be refreshed. Now return the old content and put the request into the network queue. 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. FinalRequest finalRequest = request; mDelivery.postResponse (request, response, new Runnable () {@ Override public void run () {try {mNetworkQueue.put (finalRequest);} catch (InterruptedException e) {/ / Not much we can do about this. }});}} catch (Exception e) {VolleyLog.e (e, "Unhandled exception% s", e.toString ());}

Next, take a look at the mDelivery.postResponse method.

ExecutorDelivery

As you can see from the above, mDelivery is an instance of ExecutorDelivery (passed in when creating a new RequestQueue).

The initialization code for ExecutorDelivery is as follows:

Public ExecutorDelivery (final Handler handler) {/ / Make an Executor that just wraps the handler. MResponsePoster = new Executor () {/ / java.util.concurrent.Executor; @ Override public void execute (Runnable command) {handler.post (command);}};}

You can read this article about java.util.concurrent.Executor, but I won't expand it here.

The postResponse code is as follows:

@ Override public void postResponse (Request request, Response response, Runnable runnable) {request.markDelivered (); / / Mark as distributed request.addMarker ("post-response"); mResponsePoster.execute (new ResponseDeliveryRunnable (request, response, runnable)); / / execute ResponseDeliveryRunnable} ResponseDeliveryRunnable in the handler passed in initialization is a subclass of ExecutorDelivery, which is responsible for calling the corresponding listener method: @ SuppressWarnings ("rawtypes") private class ResponseDeliveryRunnable implements Runnable {private final Request mRequest; private final Response mResponse according to the different results of request Private final Runnable mRunnable; public ResponseDeliveryRunnable (Request request, Response response, Runnable runnable) {mRequest = request; mResponse = response; mRunnable = runnable;} @ SuppressWarnings ("unchecked") @ Override public void run () {/ / execute / / If this request has canceled, finish it and don't deliver. If (mRequest.isCanceled ()) {mRequest.finish ("canceled-at-delivery"); / / calls RequestQueue's finish method return;} / / Deliver a normal response or error, depending. If (mResponse.isSuccess ()) {mRequest.deliverResponse (mResponse.result); / / call listener's onResponse (response)} 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 ();}

Next, let's look back at NetworkDispatcher's handling of network queue.

NetworkDispatcher

The source code of NetworkDispatcher is as follows:

Public class NetworkDispatcher extends Thread {private final Network mNetwork; / / BasicNetwork instance... Private final BlockingQueue request; while (true) {long startTimeMs = SystemClock.elapsedRealtime (); / / release previous request object to avoid leaking request object when mQueue is drained. Request = null; try {/ / 1. Block reading request request = mQueue.take ();} catch (InterruptedException e) {/ / We may have been interrupted because it was time to quit in network queue. 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); / / 2. Jam execution request NetworkResponse networkResponse = mNetwork.performRequest (request); request.addMarker ("network-http-complete") in the network object; / / If the server returned 304AND we delivered a response already, / / we're done-- don't deliver a second identical response. If (networkResponse.notModified & & request.hasHadResponseDelivered ()) {/ / 304indicates that the resource has not been modified request.finish ("not-modified"); continue;} / / 3. Convert NetworkResponse to Response 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) {/ / 4. Response is put in cache mCache.put (request.getCacheKey (), response.cacheEntry); request.addMarker ("network-cache-written");} / / 5. Callback result through Delivery request.markDelivered (); mDelivery.postResponse (request, response);} catch (VolleyError volleyError) {volleyError.setNetworkTimeMs (SystemClock.elapsedRealtime ()-startTimeMs); parseAndDeliverNetworkError (request, volleyError);} catch (Exception e) {VolleyLog.e (e, "Unhandled exception% s", e.toString ()); VolleyError volleyError = new VolleyError (e); volleyError.setNetworkTimeMs (SystemClock.elapsedRealtime ()-startTimeMs); mDelivery.postError (request, volleyError) } private void parseAndDeliverNetworkError (Request request, VolleyError error) {error = request.parseNetworkError (error); mDelivery.postError (request, error);}}

The processing flow of NetworkDispatcher is similar to that of CacheDispatcher, see note. The introduction to TrafficStats can be found here.

The key to the above code is the calls mNetwork.performRequest (request) and request.parseNetworkResponse (networkResponse).

Network Network is an interface with only one performRequest (Request request) method: public interface Network {public NetworkResponse performRequest (Request request) throws VolleyError;}

The implementation class of Network in the example in this article is BasicNetwork:

Public class BasicNetwork implements Network {protected static final boolean DEBUG = VolleyLog.DEBUG; private static int SLOW_REQUEST_THRESHOLD_MS = 3000; private static int DEFAULT_POOL_SIZE = 4096; protected final HttpStack mHttpStack; protected final ByteArrayPool mPool; public BasicNetwork (HttpStack httpStack) {/ / If a pool isn't passed in, then build a small default pool that will give us a lot of / / benefit and not use too much memory. This (httpStack, new ByteArrayPool (DEFAULT_POOL_SIZE));}}. Note two key members of BasicNetwork: mHttpStack and mPool, and dependence on apache: import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.StatusLine

But let's first take a look at the execution process of performRequest ():

Public NetworkResponse performRequest (Request request) throws VolleyError {long requestStart = SystemClock.elapsedRealtime (); while (true) {/ / depends on org.apache.http.HttpResponse HttpResponse httpResponse = null; byte [] responseContents = null; Map responseHeaders = Collections.emptyMap (); try {/ / 1. Generate header Map headers = new HashMap (); addCacheHeaders (headers, request.getCacheEntry ()); / / 2. Initiates a request through httpstack. Note that the action of 'initiate a request' is not performed in the request, and the request simply holds the requested information. HttpResponse = mHttpStack.performRequest (request, headers) / / 3. Get some information about the result of the request StatusLine statusLine = httpResponse.getStatusLine (); int statusCode = statusLine.getStatusCode (); responseHeaders = convertHeaders (httpResponse.getAllHeaders ()); / / 4. Use statusCode to determine whether cache if (statusCode = = HttpStatus.SC_NOT_MODIFIED) {Entry entry = request.getCacheEntry (); if (entry = = null) {return new NetworkResponse (HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime ()-requestStart);} / / take data from cache and return the new NetworkResponse entry.responseHeaders.putAll (responseHeaders) Return new NetworkResponse (HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime ()-requestStart);} / 5. Use statusCode to determine whether to redirect if (statusCode = = HttpStatus.SC_MOVED_PERMANENTLY | | statusCode = = HttpStatus.SC_MOVED_TEMPORARILY) {String newUrl = responseHeaders.get ("Location"); request.setRedirectUrl (newUrl);} / / 6. Take out the data in reponse and call it a byte array / / Some responses such as 204s do not have content. We must check. If (httpResponse.getEntity ()! = null) {/ / read data from outputstream through entityToBytes, throws IOException responseContents = entityToBytes (httpResponse.getEntity ());} else {/ / Add 0 byte response as a way of honestly representing a / / no-content request. ResponseContents = new byte [0];} / / if the request is slow, log it. Long requestLifetime = SystemClock.elapsedRealtime ()-requestStart; logSlowRequests (requestLifetime, request, responseContents, statusLine); if (statusCode

< 200 || statusCode >

{throw new IOException ();} return new NetworkResponse (statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime ()-requestStart);} 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) {/ / 7. If the entityToBytes method throw IOException int statusCode = 0; NetworkResponse networkResponse = null; if (httpResponse! = null) {statusCode = httpResponse.getStatusLine (). GetStatusCode ();} else {throw new NoConnectionError (e);} if (statusCode = = HttpStatus.SC_MOVED_PERMANENTLY | | statusCode = = HttpStatus.SC_MOVED_TEMPORARILY) {VolleyLog.e ("Request at% s has been redirected to% s", request.getOriginUrl (), request.getUrl ()) } else {VolleyLog.e ("Unexpected response code% d for% s", statusCode, request.getUrl ());} / / if reponseContent has data if (responseContents! = null) {networkResponse = new NetworkResponse (statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime ()-requestStart); / / then retry if (statusCode = = HttpStatus.SC_UNAUTHORIZED | | statusCode = = HttpStatus.SC_FORBIDDEN) {attemptRetryOnException ("auth", request, new AuthFailureError (networkResponse)) according to statusCode } else if (statusCode = = HttpStatus.SC_MOVED_PERMANENTLY | | statusCode = = HttpStatus.SC_MOVED_TEMPORARILY) {attemptRetryOnException ("redirect", request, new RedirectError (networkResponse));} else {/ / TODO: Only throw ServerError for 5xx status codes. Throw new ServerError (networkResponse);}} else {throw new NetworkError (e);}

The attemptRetryOnException () code is as follows:

Private static void attemptRetryOnException (String logPrefix, Request request, VolleyError exception) throws VolleyError {RetryPolicy retryPolicy = request.getRetryPolicy (); int oldTimeout = request.getTimeoutMs (); try {/ / key statement retryPolicy.retry (exception);} catch (VolleyError e) {request.addMarker (String.format ("% s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout)); throw;} request.addMarker (String.format ("% s-retry [timeout=%s]", logPrefix, oldTimeout));}

RetryPolicy is an interface:

Public interface RetryPolicy {public int getCurrentTimeout (); public int getCurrentRetryCount (); public void retry (VolleyError error) throws VolleyError;}

If not specified, the RetryPolicy in request is DefaultRetryPolicy, and the retry method is implemented as follows:

Public void retry (VolleyError error) throws VolleyError {mCurrentRetryCount++; mCurrentTimeoutMs + = (mCurrentTimeoutMs * mBackoffMultiplier); if (! hasAttemptRemaining ()) {throw error;}}

If the upper limit of retries has not been exceeded, no exception is thrown and is returned to the while loop of performRequest (). Next, take a look at the entityToBytes () method of BaseNetwork:

Private byte [] entityToBytes (HttpEntity entity) throws IOException, ServerError {/ / 1. New PoolingByteArrayOutputStream PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream (mPool, (int) entity.getContentLength ()); byte [] buffer = null; try {InputStream in = entity.getContent (); if (in = = null) {throw new ServerError ();} / / 2. Fetch 1024 bytes from the byte pool buffer buffer = mPool.getBuf (1024); int count; / / 3. Read data from inputStream of entity to buffer while ((count = in.read (buffer))! =-1) {/ / write buffer to PoolingByteArrayOutputStream bytes.write (buffer, 0, count);} / / 4. Return all data to return bytes.toByteArray ();} finally {try {/ / Close the InputStream and release the resources by "consuming the content". Entity.consumeContent ();} catch (IOException e) {/ / This can happen if there was an exception above that left the entity in / / an invalid state. VolleyLog.v ("Error occured when calling consumingContent");} / 5. Return the buffer to the byte pool mPool.returnBuf (buffer); bytes.close ();}} see the code comments for the execution steps. The ByteArrayPool class and PoolingByteArrayOutputStream are not expanded here. HttpStack HttpStack is an interface that is only responsible for sending out request: public interface HttpStack {public HttpResponse performRequest (Request request, Map additionalHeaders) throws IOException, AuthFailureError;}

From the initial analysis of the Volley class, HurlStack (java.net.HttpURLConnection) is used when SDK version > 9, otherwise HttpClientStack (org.apache.http.client.HttpClient) is used.

Stack each implements the performRequest () method and formally initiates the http request internally. Specific usage refers to the respective api documentation, which will not be expanded in detail here.

Request

The Request class mainly stores the parameters and the current state of the request, and does not contain the behavior related to the request:

Public abstract class Request implements Comparable {... Public interface Method {int DEPRECATED_GET_OR_POST =-1; int GET = 0; int POST = 1; int PUT = 2; int DELETE = 3; int HEAD = 4; int OPTIONS = 5; int TRACE = 6; int PATCH = 7;}. Private final int mMethod; private final String mUrl; private String mRedirectUrl; private String mIdentifier; private final int mDefaultTrafficStatsTag; private Response.ErrorListener mErrorListener; private Integer mSequence; private RequestQueue mRequestQueue; private boolean mShouldCache = true; private boolean mCanceled = false; private boolean mResponseDelivered = false; private RetryPolicy mRetryPolicy;.}

Let's analyze the request.parseNetworkResponse (networkResponse) method again. Take StringRequest as an example:

@ Override protected Response parseNetworkResponse (NetworkResponse response) {String parsed; try {parsed = new String (response.data, HttpHeaderParser.parseCharset (response.headers));} catch (UnsupportedEncodingException e) {parsed = new String (response.data);} return Response.success (parsed, HttpHeaderParser.parseCacheHeaders (response));} you can see that it simply converts data to string and then returns a response of success. The implementation of JsonObjectRequest is as follows: @ Override protected Response parseNetworkResponse (NetworkResponse response) {try {String jsonString = new String (response.data, HttpHeaderParser.parseCharset (response.headers, PROTOCOL_CHARSET)); return Response.success (new JSONObject (jsonString), HttpHeaderParser.parseCacheHeaders (response));} catch (UnsupportedEncodingException e) {return Response.error (new ParseError (e));} catch (JSONException je) {return Response.error (new ParseError (je);}}

It now converts data to string and then generates a JSONObject return.

To sum up, the general framework of Volley is as follows:

A RequestQueue contains two internal queue, cache queue and network queue. There is also a cache dispatcher and n network dispatcher, both inherited from Thread, which are responsible for executing caching and network requests, respectively. There is also a delivery that distributes the results of the request.

Cache dispatcher runs on separate threads. The cache dispatcher loop waits, fetches, and executes the request in the cache queue. Give the results to delivery.

N network dispatcher runs on separate threads. The network dispatcher loop waits, fetches, and executes the request in the network queue. Give the result to delivery and add it to cache.

Delivery is responsible for passing the result to the corresponding listener callback on the main thread.

The above is the source code analysis of the HTTP Request part of the Android Volley library. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report