上文簡(jiǎn) 單介紹了HttpClient和Tomcat服務(wù)器的交互,主角是HttpClient,然后它跟服務(wù)器交互有兩種方式即get和post。所以這個(gè) HttpClient就類似于電腦上用的瀏覽器。當(dāng)我打開(kāi)多個(gè)網(wǎng)頁(yè)的時(shí)候,并不需要開(kāi)一個(gè)網(wǎng)頁(yè)就開(kāi)一個(gè)瀏覽器,而是一個(gè)瀏覽器上面開(kāi)了好幾個(gè)網(wǎng)頁(yè)。對(duì)應(yīng)于 HttpClient,即無(wú)需連接一次就new一個(gè)HttpClient。一般,我們希望一個(gè)應(yīng)用里就一個(gè)HttpClient就ok了,就像我們的手機(jī) 或PC,沒(méi)人會(huì)呼呼的裝好幾個(gè)瀏覽器。本文即解決此問(wèn)題,代碼可以直接拿過(guò)去復(fù)用。
1、自然而然想到單例。
public class MyHttpClient {
private static HttpClient mHttpClient = null;
private static final String CHARSET = HTTP.UTF_8;
//將構(gòu)造函數(shù)封掉,只能通過(guò)對(duì)外接口來(lái)獲取HttpClient實(shí)例
private MyHttpClient(){
}
public static HttpClient getHttpClient(){
if(mHttpClient == null){
mHttpClient = new DefaultHttpClient();
}
return mHttpClient;
}
}
上面是最簡(jiǎn)單的一種單例,確實(shí)能夠滿足需要。但不能滿足多線程的要求,即當(dāng)同時(shí)完成多個(gè)Http請(qǐng)求時(shí),就出馬蛋了。
2、線程安全的HttpClient
幸運(yùn)的是android已經(jīng)提供了可以創(chuàng)建線程安全的HttpClient,即通過(guò)ClientConnectionManager 來(lái)完成。下面貼出完整代碼:
[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,注釋很詳細(xì)了啥都不說(shuō)了,可以直接使用。
3、已經(jīng)很完美了,還能不能再優(yōu)化呢??
可以使用Application來(lái)進(jìn)一步優(yōu)化創(chuàng)建HttpClient的時(shí)機(jī)及其他配置。Application的相關(guān)知識(shí)參見(jiàn):鏈接?
新建包名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里,通過(guò)mMyApplication = (MyApplication)getApplication();
mMyApplication.getHttpClient()得到HttpClient就可以使用了。
可以看到在Application的onCreate里就實(shí)例化了HttpClient,且在低內(nèi)存和關(guān)閉時(shí)關(guān)閉連接管理器,釋放資源,比2中的寫到一個(gè)普通文件里更優(yōu)。
轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/3910811.html
總結(jié)
以上是生活随笔為你收集整理的ndroid网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。