Retrying requests using request-retry handlers

来源:互联网 发布:淘宝官方折扣 编辑:程序博客网 时间:2024/06/05 13:11

Realizing that HTTP requests can fail when the user is on the move, you want to put a proper request-retry system in place so that when a request fails because of a flaky network,you can silently resend it.

1.We must employ a sensible logic for retrying failed requests

2.We must react to changes in the network configuration.

The Wi-Fi’s signal strength was too weak, so Android decided to switch over to the mobile data connection.

So instead of bothering the user with an error dialog and asking them to try again, we can do it ourselves—using a proper request retry logic.

AbstractHttpClient is the default base class that’s part of the Apache HttpClient library. Any HttpClient implementation inheriting from AbstractHttpClient, including DefaultHttpClient , will determine whether a request should be resent when an IOException occurred, and only then.

Whether a request will be retried is decided by an object of type HttpRequestRetryHandler. It defines a method called retryRequest, which is a decision method: it returns true if a request should be retried, or false if not. This method receives the exception that was raised, the number of attempts for sending that were already made, and the execution context for this request as arguments, so it can decide, based on this information, whether to retry a request.

If you don’t want to provide custom decision logic for this, and if you’re using DefaultHttpClient, then you don’t have to: DefaultHttpClient defines  DefaultHttpRequestRetryHandler for you, which has a sensible default algorithm to decide this. 

retries happen immediately after a request failed.

it retries sending the request too quickly. You could alleviate this issue by setting the maximum number of retries to a much higher number, say 20, but what we’re after is
something based on time. A better solution would be to define a custom request-retry handler that reuses the decision logic from the default handler, but adds a short amount of idle time to give the phone a chance to properly recover from whatever caused the connection failure.

public class MyMovies extends ListActivity implements Callback,OnItemLongClickListener {//create static ref to client//change type to AbstractHttpClientprivate static final AbstractHttpClient httpClient;//declare HttpRequestRetryHandlerprivate static final HttpRequestRetryHandler retryHandler;private MovieAdapter adapter;//static initializer creates objectstatic{//register dedfault schemeSchemeRegistry schemeRegistry=new SchemeRegistry();schemeRegistry.register(new Scheme("http",PlainSocketFactory.getSocketFactory(),80));HttpParams connMangerParams=new BasicHttpParams();ConnManagerParams.setMaxTotalConnections(connMangerParams, 5);ConnManagerParams.setMaxConnectionsPerRoute(connMangerParams, new ConnPerRouteBean(5));ConnManagerParams.setTimeout(connMangerParams, 15*1000);//create thread safe managerThreadSafeClientConnManager cm=new ThreadSafeClientConnManager(connMangerParams,schemeRegistry);HttpParams clientParams=new BasicHttpParams();HttpProtocolParams.setUserAgent(clientParams, "MyMovies/1.0");HttpConnectionParams.setConnectionTimeout(clientParams, 15*1000);HttpConnectionParams.setSoTimeout(clientParams, 15 * 1000);//create cutomized default HttpClienthttpClient=new DefaultHttpClient(cm,clientParams);

//inherit from default handlerretryHandler=new DefaultHttpRequestRetryHandler(5,false){public boolean retryRequest(IOException exception,int executionCount,HttpContext context){//is resent desiredif(!super.retryRequest(exception, executionCount, context)){Log.d("HTTP retry-handler", "Won't retry");return false;}try{//sleep before next executionThread.sleep(2000);}catch(InterruptedException e){}Log.d("HTTP retry-handler", "Retrying request...");return true;}};//configure object to use handlerhttpClient.setHttpRequestRetryHandler(retryHandler);}public static HttpClient getHttpClient(){return httpClient;}public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);ListView listView=getListView();Button backToTop=(Button)getLayoutInflater().inflate(R.layout.list_footer, null);backToTop.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(android.R.drawable.ic_menu_upload),null, null, null);listView.addFooterView(backToTop);this.adapter=new MovieAdapter(this);listView.setAdapter(adapter);listView.setItemsCanFocus(false);new UpdateNoticeTask(new Handler(this)).execute();//starts new download task}    public void backToTop(View view) {        getListView().setSelection(0);    }        protected void onListItemClick(ListView l, View v, int position, long id) {    this.adapter.toggleMovie(position);    this.adapter.notifyDataSetInvalidated();    }    @Overridepublic boolean handleMessage(Message msg) {// TODO Auto-generated method stubString updateNotice=msg.getData().getString("text");//reads update textAlertDialog.Builder dialog=new AlertDialog.Builder(this);dialog.setTitle("What's new");dialog.setMessage(updateNotice);//set update textdialog.setIcon(android.R.drawable.ic_dialog_info);dialog.setPositiveButton(getString(android.R.string.ok), new OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubdialog.dismiss();}});dialog.show();return false;}@Overridepublic boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position,long arg3) {// TODO Auto-generated method stubToast.makeText(this, "Getting details...", Toast.LENGTH_LONG).show();Movie movie=adapter.getItem(position);new GetMovieRatingTask(this).execute(movie.getId());return false;}}



原创粉丝点击