上文簡 單介紹了HttpClient和Tomcat服務器的交互,主角是HttpClient,然后它跟服務器交互有兩種方式即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 來完成。下面貼出完整代碼:
[java] view plaincopyprint?
<span?style="font-family:Comic?Sans?MS;font-size:18px;">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;??????????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);??????????????????????????SchemeRegistry?schReg?=?new?SchemeRegistry();??????????????schReg.register(new?Scheme("http",?PlainSocketFactory.getSocketFactory(),?80));??????????????schReg.register(new?Scheme("https",?SSLSocketFactory.getSocketFactory(),?443));??????????????????????????ClientConnectionManager?conMgr?=?new?ThreadSafeClientConnManager(params,?schReg);??????????????mHttpClient?=?new?DefaultHttpClient(conMgr,?params);??????????}??????????return?mHttpClient;??????}????????}??</span>??
方法getSaveHttpClient()即可獲得線程安全的單例httpClient,注釋很詳細了啥都不說了,可以直接使用。
3、已經很完美了,還能不能再優化呢??
可以使用Application來進一步優化創建HttpClient的時機及其他配置。Application的相關知識參見:鏈接?
新建包名org.yanzi.application,在里面新建MyApplication.java,完整代碼如下:
[java] view plaincopyprint?
<span?style="font-family:Comic?Sans?MS;font-size:18px;">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()?{??????????????????super.onCreate();??????????mHttpClient?=?this.createHttpClient();??????}????????@Override??????public?void?onTerminate()?{??????????????????super.onTerminate();??????????this.shutdownHttpClient();??????}????????@Override??????public?void?onLowMemory()?{??????????????????super.onLowMemory();??????????this.shutdownHttpClient();??????}????????????????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);??????????????????SchemeRegistry?schReg?=?new?SchemeRegistry();??????????schReg.register(new?Scheme("http",?PlainSocketFactory.getSocketFactory(),?80));??????????schReg.register(new?Scheme("https",?SSLSocketFactory.getSocketFactory(),?443));??????????????????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;??????}????}??</span>??
然后再AndroidManifest.xml理添加:
android:name="org.yanzi.application.MyApplication"
[html] view plaincopyprint?
<span?style="font-family:Comic?Sans?MS;font-size:18px;">????<application??????????android:name="org.yanzi.application.MyApplication"??????????android:allowBackup="true"??????????android:icon="@drawable/ic_launcher"??????????android:label="@string/app_name"??????????android:theme="@style/AppTheme"?>??????????<activity??????????????android:name="org.yanzi.testtomecat.MainActivity"??????????????android:label="@string/app_name"?>??????????????<intent-filter>??????????????????<action?android:name="android.intent.action.MAIN"?/>????????????????????<category?android:name="android.intent.category.LAUNCHER"?/>??????????????</intent-filter>??????????</activity>??????</application></span>??
然后再Activity里,通過mMyApplication = (MyApplication)getApplication();
mMyApplication.getHttpClient()得到HttpClient就可以使用了。
可以看到在Application的onCreate里就實例化了HttpClient,且在低內存和關閉時關閉連接管理器,釋放資源,比2中的寫到一個普通文件里更優。
轉載于:https://www.cnblogs.com/Free-Thinker/p/3910811.html
總結
以上是生活随笔為你收集整理的ndroid网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合...的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。