zoukankan      html  css  js  c++  java
  • Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合

    上文简介了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"

        <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>

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

    mMyApplication.getHttpClient()得到HttpClient就能够使用了。

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


  • 相关阅读:
    点子
    点子
    ruby crawler Anemone
    创业站
    我友网 没前途
    创意
    电商站
    尿布
    创意
    青番茄好项目
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4026627.html
Copyright © 2011-2022 走看看