If you plan to develop applications that only target Android 2.2 or newer, you may consider skipping this technique.
You’re running threads that need to communicate with a web server through a single shared instance of HttpClient, and you must therefore make sure that connections are established in a mutually exclusive, thread-safe manner.
ThreadSafeClientConnManager. This connection manager doesn’t handle a single connection, but a pool of them, where each connection can be taken from the pool, allocated to a thread (which then has exclusive access to it), and returned to the pool once the thread yields it. If the same or another thread claims a connection for the same route, then a connection can be immediately reused from the pool without the need to first close and reopen it, thereby avoiding the overhead of the handshake performed by HTTP when establishing a new connection.
Connection pooling isn’t based on thread identity (the same thread getting the same connection back every time), but on routes.
This means that a connection for a request can only be reused from the pool when the request goes to the same target host via the same intermediate hosts using the same layering or tunneling parameters.
One caveat with setting a connection manager manually is that you need to supply a set of HTTP configuration parameters and a protocol scheme registry, even if you
don’t want these things to be different from what DefaultHttpClient uses by default with its SingleClientConnManager.
XML, as a means of configuration, can only be used for resources such as views and the application manifest. Anything else you’ll have to write out in Java code, including your HTTP configuration.
You can use a stati:c initializer to set-up a thread-safe HttpClient instance
public class MyMovies extends ListActivity implements Callback {
//create static ref to client
private static final AbstractHttpClient httpClient;
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);
retryHandler=new DefaultHttpRequestRetryHandler(5,false){
public boolean retryRequest(IOException exception,int executionCount,HttpContext context){
if(!super.retryRequest(exception, executionCount, context)){
Log.d("HTTP retry-handler", "Won't retry");
return false;
}
try{
Thread.sleep(2000);
}catch(InterruptedException e){
}
Log.d("HTTP retry-handler", "Retrying request...");
return true;
}
};
}
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;
}
}
if you’re targeting Android 2.2 or above, you don’t have to do anything shown in this technique yourself! As we mentioned briefly before, Android bundles a custom implementation of HttpClient called AndroidHttpClient with that version. This implementation has already been optimized for mobile use, and it does all the stuff like
setting proper timeouts and a thread-safe connection manager. It also supports HTTPS by default. In order to use it, you’d replace the code at F in listing 9.4 with this:
httpClient = AndroidHttpClient.newInstance("MyMovies/1.0");