简介了HttpClient和Tomcatserver的交互,主角是HttpClient,然后它跟server交互有两种方式即get和post。所以这个HttpClient就相似于电脑上用的浏览器。当我打开多个网页的时候,并不须要开一个网页就开一个浏览器,而是一个浏览器上面开了好几个网页。相应于HttpClient,即无需连接一次就new一个HttpClient。一般,我们希望一个应用里就一个HttpClient就ok了,就像我们的手机或PC,没人会呼呼的装好几个浏览器。本文即解决此问题,代码能够直接拿过去复用。
1、自然而然想到单例。
public class MyHttpClient { private static HttpClient mHttpClient = null; private static final String CHARSET = HTTP.UTF_8; //将构造函数封掉,仅仅能通过对外接口来获取HttpClient实例 private MyHttpClient(){ } public static HttpClient getHttpClient(){ if(mHttpClient == null){ mHttpClient = new DefaultHttpClient(); } return mHttpClient; }}
上面是最简单的一种单例,确实能够满足须要。但不能满足多线程的要求,即当同一时候完毕多个Http请求时,就出马蛋了。
2、线程安全的HttpClient
幸运的是android已经提供了能够创建线程安全的HttpClient,即通过ClientConnectionManager 来完毕。以下贴出完整代码:
package org.yanzi.webutil;import org.apache.http.HttpVersion;import org.apache.http.client.HttpClient;import org.apache.http.conn.ClientConnectionManager;import org.apache.http.conn.params.ConnManagerParams;import org.apache.http.conn.scheme.PlainSocketFactory;import org.apache.http.conn.scheme.Scheme;import org.apache.http.conn.scheme.SchemeRegistry;import org.apache.http.conn.ssl.SSLSocketFactory;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.params.HttpProtocolParams;import org.apache.http.protocol.HTTP;public class MyHttpClient { private static HttpClient mHttpClient = null; private static final String CHARSET = HTTP.UTF_8; //将构造函数封掉,仅仅能通过对外接口来获取HttpClient实例 private MyHttpClient(){ } public static HttpClient getHttpClient(){ if(mHttpClient == null){ mHttpClient = new DefaultHttpClient(); } return mHttpClient; } public static synchronized HttpClient getSaveHttpClient(){ if(mHttpClient == null){ HttpParams params = new BasicHttpParams(); //设置基本參数 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); //超时设置 /*从连接池中取连接的超时时间*/ ConnManagerParams.setTimeout(params, 1000); /*连接超时*/ HttpConnectionParams.setConnectionTimeout(params, 2000); /*请求超时*/ HttpConnectionParams.setSoTimeout(params, 4000); //设置HttpClient支持HTTp和HTTPS两种模式 SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); //使用线程安全的连接管理来创建HttpClient ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg); mHttpClient = new DefaultHttpClient(conMgr, params); } return mHttpClient; } }方法getSaveHttpClient()就可以获得线程安全的单例httpClient,凝视非常具体了啥都不说了,能够直接使用。
3、已经非常完美了,还能不能再优化呢?
能够使用Application来进一步优化创建HttpClient的时机及其它配置。Application的相关知识參见:
新建包名org.yanzi.application,在里面新建MyApplication.java,完整代码例如以下:
package org.yanzi.application;import org.apache.http.HttpVersion;import org.apache.http.client.HttpClient;import org.apache.http.conn.ClientConnectionManager;import org.apache.http.conn.params.ConnManagerParams;import org.apache.http.conn.scheme.PlainSocketFactory;import org.apache.http.conn.scheme.Scheme;import org.apache.http.conn.scheme.SchemeRegistry;import org.apache.http.conn.ssl.SSLSocketFactory;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.params.HttpProtocolParams;import org.apache.http.protocol.HTTP;import android.app.Application;public class MyApplication extends Application { private HttpClient mHttpClient = null; private static final String CHARSET = HTTP.UTF_8; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mHttpClient = this.createHttpClient(); } @Override public void onTerminate() { // TODO Auto-generated method stub super.onTerminate(); this.shutdownHttpClient(); } @Override public void onLowMemory() { // TODO Auto-generated method stub super.onLowMemory(); this.shutdownHttpClient(); } /**创建HttpClient实例 * @return */ private HttpClient createHttpClient(){ HttpParams params = new BasicHttpParams(); //设置基本參数 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); //超时设置 /*从连接池中取连接的超时时间*/ ConnManagerParams.setTimeout(params, 1000); /*连接超时*/ HttpConnectionParams.setConnectionTimeout(params, 2000); /*请求超时*/ HttpConnectionParams.setSoTimeout(params, 4000); //设置HttpClient支持HTTp和HTTPS两种模式 SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); //使用线程安全的连接管理来创建HttpClient ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg); HttpClient client = new DefaultHttpClient(conMgr, params); return client; } private void shutdownHttpClient(){ if(mHttpClient != null && mHttpClient.getConnectionManager() != null){ mHttpClient.getConnectionManager().shutdown(); } } public HttpClient getHttpClient(){ return mHttpClient; }}然后再AndroidManifest.xml理加入:
android:name="org.yanzi.application.MyApplication"
然后再Activity里,通过mMyApplication = (MyApplication)getApplication();
mMyApplication.getHttpClient()得到HttpClient就能够使用了。
能够看到在Application的onCreate里就实例化了HttpClient,且在低内存和关闭时关闭连接管理器,释放资源,比2中的写到一个普通文件中更优。