现在的位置: 首页 > 综合 > 正文

Retrying requests using request-retry handlers

2017年12月24日 ⁄ 综合 ⁄ 共 5084字 ⁄ 字号 评论关闭

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 AbstractHttpClient
	private static final AbstractHttpClient httpClient;
	//declare HttpRequestRetryHandler
	private static final HttpRequestRetryHandler retryHandler;
	
	private MovieAdapter adapter;
	//static initializer creates object
	static{
		//register dedfault scheme
		SchemeRegistry 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 manager
		ThreadSafeClientConnManager 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 HttpClient
		httpClient=new DefaultHttpClient(cm,clientParams);

		//inherit from default handler
		retryHandler=new DefaultHttpRequestRetryHandler(5,false){
			public boolean retryRequest(IOException exception,int executionCount,HttpContext context){
				//is resent desired
				if(!super.retryRequest(exception, executionCount, context)){
					Log.d("HTTP retry-handler", "Won't retry");
					return false;
				}
				
				try{
					//sleep before next execution
					Thread.sleep(2000);
				}catch(InterruptedException e){
					
				}
				Log.d("HTTP retry-handler", "Retrying request...");
				return true;
			}
		};
		//configure object to use handler
		httpClient.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();
    }
    
	@Override
	public boolean handleMessage(Message msg) {
		// TODO Auto-generated method stub
		String updateNotice=msg.getData().getString("text");//reads update text
		AlertDialog.Builder dialog=new AlertDialog.Builder(this);
		dialog.setTitle("What's new");
		dialog.setMessage(updateNotice);//set update text
		dialog.setIcon(android.R.drawable.ic_dialog_info);
		dialog.setPositiveButton(getString(android.R.string.ok), new OnClickListener(){
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				dialog.dismiss();
			}
		});
		dialog.show();
		return false;
	}

	@Override
	public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position,
			long arg3) {
		// TODO Auto-generated method stub
		Toast.makeText(this, "Getting details...", Toast.LENGTH_LONG).show();
		Movie movie=adapter.getItem(position);
		new GetMovieRatingTask(this).execute(movie.getId());
		return false;
	}
}

抱歉!评论已关闭.