Volley source code parsing (vi) The dispute between--hurlstack and Httpclientstack

Source: Internet
Author: User
Tags response code

There are two ways to load the network in volley, each of which is hurlstack and httpclientstack. Let's look at a piece of code in Volley.java

if (stack = = Null) {//assume No qualification            for stack if (Build.VERSION.SDK_INT >= 9) {//ADK version number at 9 or above                stack = new Hurlstack (); 
   

thus, Assuming that no stack is set, the current ADK version number is the active choice. HttpClient has fewer bugs before the Android 2.2 version Number. So using it is the best choice.

And after the Android 2.3 version number and Later. HttpURLConnection is the best choice.

Its API is Simple. Small size, making it ideal for Android Projects. Compression and caching mechanism can effectively reduce network access to the traffic, in the speed and power saving also played a big role. For the new application should be more inclined to use httpurlconnection, because in the future work of which we will also put a lot of other time on the optimization httpurlconnection Above.

To this end, we need to look at these two categories Separately. Before looking at these two, let's look at them a simple parent class Httpstack

/** * An HTTP stack Abstraction. * Abstract HTTP Stack */public interface httpstack {    /**     * Performs an HTTP request with the given Parameters.     * Based on the number of References. Run HTTP request     * <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>< c5/>*     * @param request the request to perform     * @param additionalheaders additional headers-be sent together WI Th     *         {@link request#getheaders ()}     * @return The HTTP response */public    HttpResponse Performrequest (request<?> Request, map<string, string> additionalheaders)        throws ioexception, authfailureerror;}

The parent class essentially stipulates that a subclass must have a request for data based on requests, and a method that returns the HttpResponse class


OK, Next we look at hurlstack, this class uses HttpURLConnection as a connection, in the ADK higher version of the recommended use (in fact, the market now 2.3 of the system is very rare)

We look directly at the core method of this class Performrequest ()

@Override public HttpResponse performrequest (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);            If (murlrewriter! = Null) {String rewritten = Murlrewriter.rewriteurl (url);            if (rewritten = = Null) {throw new IOException ("url blocked by rewriter:" + url);        } URL = rewritten;        } URL parsedurl = new URL (url); HttpURLConnection connection = openconnection (parsedurl, request);//open connection for (String HeaderName:map.keySet ()) {//        Join request number Connection.addrequestproperty (headername, Map.get (headername)); } setconnectionparametersforrequest (connection, Request);//set The requested Mode//Initialize HttpResponse with the data from The Httpurlconnection. ProtocolVersion protocolversion = new ProtocolVersion ("HTTP", 1, 1);//http protocol int responsecode = CONNECTION.GETRESPO Nsecode ();//gets The response status if (responsecode = =-1) {//-1 description is not responding, throws an exception//-1 is returned by Getresponsecode () if th            E response code could not being Retrieved.            Signal to the caller that something is wrong with the Connection.        throw new IOException ("Could not retrieve response code from httpurlconnection."); } statusline responsestatus = new Basicstatusline (protocolversion, Connection.getresponsecode (), con        Nection.getresponsemessage ());//response Status Class basichttpresponse response = new Basichttpresponse (responsestatus);  Response.setentity (entityfromconnection (connection));//parse response entity for (entry<string, list<string>> Header:  Connection.getheaderfields (). entryset ()) {//add response header if (header.getkey () = null) {header h = new Basicheader (HEADER.GEtkey (), header.getvalue (). get (0));            Response.AddHeader (h);    }} return response; }

The whole method is divided into several steps, the first of which is the request Parameters. Store to map where

hashmap<string, string> map = new hashmap<string, string> ();        Map.putall (request.getheaders ());        Map.putall (additionalheaders);

Then open the URL connection

URL parsedurl = new URL (url);        HttpURLConnection connection = openconnection (parsedurl, request);//open Connection
See OpenConnection () method

/** * Opens a {@link httpurlconnection} with Parameters. * Open Network connection * @param URL * @return an open connection * @throws ioexception */private httpurlconnection o Penconnection (url url, request<?)

> Request) throws ioexception {httpurlconnection connection = createconnection (url); int TIMEOUTMS = Request.gettimeoutms (); Connection.setconnecttimeout (timeoutms); Connection.setreadtimeout (timeoutms); Connection.setusecaches (false); Connection.setdoinput (true); Use caller-provided custom sslsocketfactory, if any, for https if ("https". equals (url.getprotocol ()) && msslsocketfactory! = Null) {//https ((httpsurlconnection) connection). setsslsocketfactory (msslsocketfactory); } return connection; }/**     * Create a {@link httpurlconnection} for the specified {@code Url}.   &nbs P */    protected HttpURLConnection createconnection (url Url) throws IOException {         return (httpurlconnection) url.openconnection ();   }

The main method is to call Url.openconnevtion () and return a httpurlconnection object. Some of the timeout settings are provided by the request Itself.

Also depending on whether the URL has https. Set setsslsocketfactory for HttpURLConnection (msslsocketfactory objects are passed in the constructor METHOD)

Get httpurlconnection, Set Request parameters

For (String headerName:map.keySet ()) {//join request number            Connection.addrequestproperty (headername, map.get (headername));        }
Then determine how the request is (get,post or something Else)

Setconnectionparametersforrequest (connection, Request);//set The requested mode
Setconnectionparametersforrequest method:
@SuppressWarnings ("deprecation")/** * Set Request method * @param connection * @param request * @throws Ioexceptio n * @throws authfailureerror */* package */static void Setconnectionparametersforrequest (httpurlconnecti On connection, request<?> Request) throws ioexception, authfailureerror {switch (request.getmetho D ()) {case Method.deprecated_get_or_post://this is the DEPRECATED-on-the-needs to be handle                D for Backwards Compatibility.  If the request ' s post body is null, then the assumption is, and the request is/GET.                Otherwise, it is assumed and the request is a POST.                byte[] postbody = Request.getpostbody (); If (postbody! = Null) {//Prepare Output. There is no need to set content-length explicitly,//since the is handled by HttpURLConnection using The size of the PREPARED//OUTPUT Stream.                    Connection.setdooutput (true);                    Connection.setrequestmethod ("POST");                    Connection.addrequestproperty (header_content_type, Request.getpostbodycontenttype ());                    DataOutputStream out = new DataOutputStream (connection.getoutputstream ());                    Out.write (postbody);                Out.close ();            } break;                Case Method.get://does necessary to set the request Method because connection defaults to GET                Being explicit Here.                Connection.setrequestmethod ("GET");            Break                Case Method.DELETE:connection.setRequestMethod ("DELETE");            Break                Case Method.POST:connection.setRequestMethod ("POST");                Addbodyifexists (connection, request);            Break Case Method.PUT:conneCtion.setrequestmethod ("PUT");                Addbodyifexists (connection, request);            Break                Case Method.HEAD:connection.setRequestMethod ("HEAD");            Break                Case Method.OPTIONS:connection.setRequestMethod ("OPTIONS");            Break                Case Method.TRACE:connection.setRequestMethod ("TRACE");            Break                Case Method.PATCH:connection.setRequestMethod ("PATCH");                Addbodyifexists (connection, request);            Break        Default:throw New IllegalStateException ("Unknown method type."); }    }

Finally get the Response. Wraps the response header information into a Statusline object and then wraps it into a Basichttpresponse object

Statusline responsestatus = new Basicstatusline (protocolversion,                connection.getresponsecode (), Connection.getresponsemessage ());//response Status Class        basichttpresponse response = new Basichttpresponse (responsestatus);

Then add response content for Basichttpresponse

Response.setentity (entityfromconnection (connection));//parse Response Entity
Entityfromconnection (httpurlconnection Connection) method:
/**     * Initializes a {@link httpentity} from the given {@link httpurlconnection}.     * <br> Parse out response entity     * @param connection     * @return An httpentity populated with data from <CODE>CONNECTION&L T;/code>.     *    /private static httpentity entityfromconnection (httpurlconnection connection) {        basichttpentity entity = new Basichttpentity ();        InputStream inputstream;        Try {            inputstream = connection.getinputstream ();        } catch (ioexception ioe) {            InputStream = Connection.geterrorstream ();        }        Entity.setcontent (inputstream);        Entity.setcontentlength (connection.getcontentlength ());        Entity.setcontentencoding (connection.getcontentencoding ());        Entity.setcontenttype (connection.getcontenttype ());        return entity;    }
finally, Add the response header content

For (entry<string, list<string>> header:connection.getHeaderFields (). entryset ()) {//add response header            if ( Header.getkey () = Null) {                Header h = new Basicheader (header.getkey (), header.getvalue (). get (0));                Response.AddHeader (h);            }        }
Ok. This returns a HttpResponse object with complete Information. The whole process is relatively simple and is a regular network request Content.


Next we look at the realization of Httpclientstack

Same. Take a direct look at the Performrequest () method

@Override public    httpresponse performrequest (request<?> Request, map<string, string> Additionalheaders)            throws ioexception, authfailureerror {        httpurirequest HttpRequest = Createhttprequest ( request, additionalheaders);        Addheaders (httprequest, Additionalheaders);//add Cache header        addheaders (httprequest, request.getheaders ());//join Request Header        onpreparerequest (httprequest);//request preprocessing        Httpparams httpparams = Httprequest.getparams ();        int TIMEOUTMS = Request.gettimeoutms ();        Todo:reevaluate This connection timeout based on + Wide-scale        //data collection and possibly different for wif I vs. 3G.        Httpconnectionparams.setconnectiontimeout (httpparams,);        Httpconnectionparams.setsotimeout (httpparams, timeoutms);        return Mclient.execute (httprequest);    }

The request step, first of all, depends on the Request. Constructs a httpurirequest object, and sets the request parameters

Httpurirequest HttpRequest = createhttprequest (request, additionalheaders);
Createhttprequest () method:
/** * Creates the appropriate subclass of Httpurirequest for passed in Request. * Returns the subclass of the corresponding httpurirequest */@SuppressWarnings ("deprecation")/*/protected */static httpurirequest Crea according to the request method        Tehttprequest (request<?> Request, map<string, string> Additionalheaders) throws Authfailureerror { Switch (request.getmethod ()) {case method.deprecated_get_or_post: {//this is the Depre                Cated-on-the-needs to is handled for backwards Compatibility.  If the request ' s post body is null, then the assumption is, and the request is/GET.                Otherwise, it is assumed and the request is a POST.                byte[] postbody = Request.getpostbody ();                    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 ());            }} 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 ());                Postrequest.addheader (header_content_type, Request.getbodycontenttype ());            Setentityifnonemptybody (postrequest, Request);//set The requested parameter return postrequest;                } case method.put: {httpput putrequest = new Httpput (request.geturl ());                Putrequest.addheader (header_content_type, Request.getbodycontenttype ());                Setentityifnonemptybody (putrequest, request); Return Putrequest;            } Case Method.HEAD:return new Httphead (request.geturl ());            Case Method.OPTIONS:return New Httpoptions (request.geturl ());            Case Method.TRACE:return New HttpTrace (request.geturl ());                Case Method.patch: {httppatch patchrequest = new Httppatch (request.geturl ());                Patchrequest.addheader (header_content_type, Request.getbodycontenttype ());                Setentityifnonemptybody (patchrequest, request);            Return patchrequest;        } default:throw new IllegalStateException ("Unknown request method."); }    }
From the Createhttprequest () method can be Seen. In httpclient, the only way to do this is to request a new httpget/httppost/.... The object will be able (and urlstack This step is really connnection)

The request header is then set for the Httpurirequest object

Addheaders (httprequest, Additionalheaders);//add Cache header        addheaders (httprequest, request.getheaders ());//join Request Header
Addheaders method:
/**     * Add response header     * @param httprequest     * @param headers * * *    private static void Addheaders (httpurirequest httprequest, map<string, string> headers) {for        (String key:headers.keySet ()) {            Httprequest.setheader ( key, headers.get (key));        }    }
finally, give the Httpurirequest object to HttpClient to run

return Mclient.execute (httprequest);

Ok,httpclientstack is simpler than we thought. At least it's simpler than hurlstack, which is of course. Because of the httpclient approach, the essence is the encapsulation of the urlconnection, but the package is not perfect. therefore, the difference between version numbers is Caused.


To this end, we introduce the two classes of Hurlstack and httpclientstack, and at the same time explain where real network requests Run.

The next article will come to understand the use of response<t>,response<t> is volley throughout the Process. The end goal, as a response Entity. Let's take a look at how response<t> is Designed.



Volley source code parsing (vi) The dispute between--hurlstack and Httpclientstack

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.