«

Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合

时间:2024-3-2 17:54     作者:韩俊     分类: Android


zz:http://blog.csdn.net/yanzi1225627/article/details/24937439


上文简单介绍了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;
//将构造函数封掉,只能通过对外接口来获取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(&quot;http&quot;, PlainSocketFactory.getSocketFactory(), 80));  
        schReg.register(new Scheme(&quot;https&quot;, SSLSocketFactory.getSocketFactory(), 443));  
        //使用线程安全的连接管理来创建HttpClient  
        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() {
// 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(&quot;http&quot;, PlainSocketFactory.getSocketFactory(), 80));  
    schReg.register(new Scheme(&quot;https&quot;, SSLSocketFactory.getSocketFactory(), 443));  
    //使用线程安全的连接管理来创建HttpClient  
    ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);  
    HttpClient client = new DefaultHttpClient(conMgr, params);  
    return client;  
}  
private void shutdownHttpClient(){  
    if(mHttpClient != null &amp;&amp; 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" />

            &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;  
        &lt;/intent-filter&gt;  
    &lt;/activity&gt;  
&lt;/application&gt;&lt;/span&gt;  



然后再Activity里,通过mMyApplication = (MyApplication)getApplication();

mMyApplication.getHttpClient()得到HttpClient就可以使用了。

可以看到在Application的onCreate里就实例化了HttpClient,且在低内存和关闭时关闭连接管理器,释放资源,比2中的写到一个普通文件里更优。

标签: android

热门推荐