Volley time-out retry mechanism base usage
Volley provides a configurable timeout retry mechanism for developers, and we only need to set a custom retrypolicy for our request when we use them.
The reference setup code is as follows:
intDefault_timeout_ms =10000;intDefault_max_retries =3; Stringrequest stringrequest =NewStringrequest (Request.Method.GET, URL,NewResponse.listener<string> () {@Override Public void Onresponse(String s) {Logutil.i (TAG,"res="+ s); }},NewResponse.errorlistener () {@Override Public void Onerrorresponse(Volleyerror volleyerror) {LOGUTIL.E (TAG, volleyerror.tostring ()); }});//Set volley timeout retry policyStringrequest.setretrypolicy (NewDefaultretrypolicy (Default_timeout_ms, Default_max_retries, Defaultretrypolicy.default_backoff_mult)); Requestqueue Requestqueue = volleymanager.getinstance (context). Getrequestqueue (); Requestqueue.add (stringRequest);
Basic knowledge
Before explaining the volley time-out retry principle, you need to popularize the exception associated with the timeout retry.
Org.apache.http.conn.ConnectTimeoutException
whiletoanorforanfroman HttpConnectionManager.
The connection HTTP server timed out or waited for Httpconnectionmanager to return an available connection timeout, commonly known as a request timeout.
Java.net.SocketTimeoutException
thattimeoutonreador accept.
The socket communication timed out, that is, when reading data from the server timeout, commonly known as response timeout.
Volley is the time-out retry by catching these two exceptions.
Volley Catching timeout exception
Read the previous volley source analysis of the classmate, should know that the volley is through the basicnetwork to perform network requests. The relevant source code is as follows:
@Override PublicNetworkresponseperformrequest(request<?> Request)throwsVolleyerror {//Record the time at which the request started, facilitating timeout retries LongRequeststart = Systemclock.elapsedrealtime (); while(true) {HttpResponse HttpResponse =NULL;byte[] responsecontents =NULL; map<string, string> responseheaders = Collections.emptymap ();Try{// ...... Omit section add http-header code //Call Hurlstack's Performrequest method to execute a network request and store the request result in the HttpResponse variableHttpResponse = mhttpstack.performrequest (request, headers); Statusline statusline = Httpresponse.getstatusline ();intStatusCode = Statusline.getstatuscode (); Responseheaders = Convertheaders (Httpresponse.getallheaders ());// ...... Omit part of the code for return value processing return NewNetworkresponse (StatusCode, responsecontents, Responseheaders,false, Systemclock.elapsedrealtime ()-Requeststart); }Catch(Sockettimeoutexception e) {//Capture Response TimeoutAttemptretryonexception ("Socket", request,NewTimeouterror ()); }Catch(Connecttimeoutexception E) {//Capture Request timed outAttemptretryonexception ("Connection", request,NewTimeouterror ()); }Catch(IOException e) {//Omit exception handling for IOException, regardless of server-side error retry mechanism} }}Private void attemptretryonexception(String Logprefix, request<?> Request, Volleyerror exception)throwsvolleyerror{Retrypolicy retrypolicy = Request.getretrypolicy ();intOldtimeout = Request.gettimeoutms (); Retrypolicy.retry (Exception); LOG.E ("Volley", String.Format ("%s-retry [timeout=%s]", Logprefix, Oldtimeout));}
Because the Basicnetwork class is using a java while(true)
package connection request, if you catch a program that throws sockettimeoutexception or connecttimeoutexception, Does not jump out of the loop operation, but enters into the Attemptretryonexception method.
If the Volleyerror exception is not thrown in the Attemptretryonexception method, the final program can enter the while loop again to complete the timeout retry mechanism.
Next, let's take a look at how Retrypolicy determines if a timeout retry is required, and how to stop the timeout retry.
Retrypolicy.java
Retrypolicy is an interface definition, the source code for Chinese annotations is as follows:
/** * Request请求的重试策略类. */@SuppressWarnings("unused")publicinterface RetryPolicy { /** * 获取当前请求的超时时间 */ int getCurrentTimeout(); /** * 获取当前请求的重试次数 */ int getCurrentRetryCount(); /** * 实现类需要重点实现的方法,用于判断当前Request是否还需要再进行重试操作 */ voidthrows VolleyError;}
Retrypolicy is just the request retry policy interface defined by volley and also provides a Defaultretrypolicy implementation class to help developers quickly implement custom request retry functions.
Defaultretrypolicy.java
The source code of Chinese notes is as follows:
Public class defaultretrypolicy implements retrypolicy { /** * Request Current Timeout */ Private intMcurrenttimeoutms;/** * Request Current Retry count */ Private intMcurrentretrycount;/** * Request up to retry times * / Private Final intMmaxnumretries;/** * Request Timeout Time product factor */ Private Final floatMbackoffmultiplier;/** * Volley default time-out (2.5s) */ Public Static Final intDefault_timeout_ms =2500;/** * Volley default number of retries (0 times, no request retry) */ Public Static Final intDefault_max_retries =0;/** * The product factor for the default time-out period. * Take the default time-out of 2.5s for example: * 1. Default_backoff_mult = 1f, the time-out for each httpurlconnection setting is 2.5s*1f*mcurrentretrycount. * 2. Default_backoff_mult = 2f, the second time-out is: 2.5s+2.5s*2=7.5s, the third time-out is: 7.5s+7.5s*2=22.5s */ Public Static Final floatDefault_backoff_mult =1F/** * Request's default Retry policy constructor * Timeout: 2500ms * Retry: 0 times * Timeout factor: 1f */ Public Defaultretrypolicy() { This(Default_timeout_ms, Default_max_retries, Default_backoff_mult); }/** * Developer Customized Request Retry Policy constructor * * @param INITIALTIMEOUTMS Timeout * @param maxnumretries Maximum retries * @param backoffmultiplier timeout Time product factor */ Public Defaultretrypolicy(intInitialtimeoutms,intMaxnumretries,floatBackoffmultiplier) {Mcurrenttimeoutms = Initialtimeoutms; Mmaxnumretries = maxnumretries; Mbackoffmultiplier = Backoffmultiplier; }@Override Public int Getcurrenttimeout() {returnMcurrenttimeoutms; }@Override Public int Getcurrentretrycount() {returnMcurrentretrycount; }@Override Public void Retry(Volleyerror error)throwsVolleyerror {//Add retry attemptsMcurrentretrycount + +;//Cumulative time-outMcurrenttimeoutms + = Mcurrenttimeoutms * Mbackoffmultiplier;//Determine if there are any remaining times, and if not, throw a Volleyerror exception if(!hasattemptremaining ()) {ThrowError } }/** * Determine if the current request retries more than the maximum number of retries * / Private Boolean hasattemptremaining() {returnMcurrenttimeoutms <= mmaxnumretries; }}
At the beginning of this article, I talked about how to set up custom Retrypolicy, combined with the Chinese Defaultretrypolicy source code, I believe it is easy to understand the parameters of custom retrypolicy and the role of the meaning.
Now there may be a question, why Defaultretrypolicy retry method throws the Volleyerror exception, you can exit the Basicnetwork class Performrequest while (true) loop it?
This is because Basicnetwork does not catch the volleyerror exception, so the exception that is not Try&catch live will terminate the current program run, continue to throw out, this time back to the Networkdispatcher class, the relevant source code is as follows:
@Override Public void Run() {android.os.Process.setThreadPriority (process.thread_priority_background); while(true) {LongStarttimems = Systemclock.elapsedrealtime (); Request<?> request;Try{//using Blockingqueue to implement the producer-consumer model. //consumer is the dispatch thread. //producer is requesting a network request.Request = Mqueue.take (); }Catch(Interruptedexception e) {//We may have been interrupted because it is time to quit. if(Mquit) {return; }Continue; }Try{if(Request.iscanceled ()) {Continue; } addtrafficstatstag (Request);//Where the network request is actually executed. (Basicnetwork is thrown here because of a timeout volleyerror)Networkresponse networkresponse = mnetwork.performrequest (request); Mdelivery.postresponse (request, response); }Catch(Volleyerror volleyerror) {//Capture Volleyerror exception, Handler callback method in Errorlistener set by the main thread.Volleyerror.printstacktrace (); Volleyerror.setnetworktimems (Systemclock.elapsedrealtime ()-starttimems); Parseanddelivernetworkerror (Request, volleyerror); }Catch(Exception e) {Volleyerror Volleyerror =NewVolleyerror (e); Volleyerror.setnetworktimems (Systemclock.elapsedrealtime ()-starttimems); Mdelivery.posterror (Request, volleyerror); } }}
From the source above, it can be seen that request cannot continue to throw after the retry Volleyerror exception, will be captured by Networkdispatcher, and then through delivery to callback user-set Errorlistener.
Summary
At this point, volley's time-out retry mechanism is analyzed, at the end of this article we recommend the volley default retry policy parameters.
Default timeout: Volley The default 2500ms is a little short, you can set the default time-out for HttpClient, which is 10000ms.
Default number of retries: 3 recommendations, can be adjusted according to the business itself.
Default timeout factor: It is recommended to use the default value of Defaultretrypolicy 1f, otherwise the curve will grow too fast to cause the page to wait for a long time.
More detailed volley source analysis, you can refer to my GitHub project: Volley source analysis
Volley timeout retry mechanism detailed