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

    上文简 单介绍了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 来完成。下面贴出完整代码:

    1. <span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.webutil;  
    2.   
    3. import org.apache.http.HttpVersion;  
    4. import org.apache.http.client.HttpClient;  
    5. import org.apache.http.conn.ClientConnectionManager;  
    6. import org.apache.http.conn.params.ConnManagerParams;  
    7. import org.apache.http.conn.scheme.PlainSocketFactory;  
    8. import org.apache.http.conn.scheme.Scheme;  
    9. import org.apache.http.conn.scheme.SchemeRegistry;  
    10. import org.apache.http.conn.ssl.SSLSocketFactory;  
    11. import org.apache.http.impl.client.DefaultHttpClient;  
    12. import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;  
    13. import org.apache.http.params.BasicHttpParams;  
    14. import org.apache.http.params.HttpConnectionParams;  
    15. import org.apache.http.params.HttpParams;  
    16. import org.apache.http.params.HttpProtocolParams;  
    17. import org.apache.http.protocol.HTTP;  
    18.   
    19. public class MyHttpClient {  
    20.     private static HttpClient mHttpClient = null;  
    21.     private static final String CHARSET = HTTP.UTF_8;  
    22.     //将构造函数封掉,只能通过对外接口来获取HttpClient实例  
    23.     private MyHttpClient(){  
    24.   
    25.     }  
    26.     public static HttpClient getHttpClient(){  
    27.         if(mHttpClient == null){  
    28.             mHttpClient = new DefaultHttpClient();  
    29.         }  
    30.         return mHttpClient;  
    31.     }  
    32.     public static synchronized HttpClient getSaveHttpClient(){  
    33.         if(mHttpClient == null){  
    34.             HttpParams params = new BasicHttpParams();  
    35.             //设置基本参数  
    36.             HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  
    37.             HttpProtocolParams.setContentCharset(params, CHARSET);  
    38.             HttpProtocolParams.setUseExpectContinue(params, true);  
    39.             //超时设置  
    40.             /*从连接池中取连接的超时时间*/  
    41.             ConnManagerParams.setTimeout(params, 1000);  
    42.             /*连接超时*/  
    43.             HttpConnectionParams.setConnectionTimeout(params, 2000);  
    44.             /*请求超时*/  
    45.             HttpConnectionParams.setSoTimeout(params, 4000);  
    46.             //设置HttpClient支持HTTp和HTTPS两种模式  
    47.             SchemeRegistry schReg = new SchemeRegistry();  
    48.             schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
    49.             schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));  
    50.             //使用线程安全的连接管理来创建HttpClient  
    51.             ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);  
    52.             mHttpClient = new DefaultHttpClient(conMgr, params);  
    53.         }  
    54.         return mHttpClient;  
    55.     }  
    56.       
    57. }  
    58. </span>  


    方法getSaveHttpClient()即可获得线程安全的单例httpClient,注释很详细了啥都不说了,可以直接使用。

    3、已经很完美了,还能不能再优化呢? 

    可以使用Application来进一步优化创建HttpClient的时机及其他配置。Application的相关知识参见:链接 

    新建包名org.yanzi.application,在里面新建MyApplication.java,完整代码如下:

    1. <span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.application;  
    2.   
    3. import org.apache.http.HttpVersion;  
    4. import org.apache.http.client.HttpClient;  
    5. import org.apache.http.conn.ClientConnectionManager;  
    6. import org.apache.http.conn.params.ConnManagerParams;  
    7. import org.apache.http.conn.scheme.PlainSocketFactory;  
    8. import org.apache.http.conn.scheme.Scheme;  
    9. import org.apache.http.conn.scheme.SchemeRegistry;  
    10. import org.apache.http.conn.ssl.SSLSocketFactory;  
    11. import org.apache.http.impl.client.DefaultHttpClient;  
    12. import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;  
    13. import org.apache.http.params.BasicHttpParams;  
    14. import org.apache.http.params.HttpConnectionParams;  
    15. import org.apache.http.params.HttpParams;  
    16. import org.apache.http.params.HttpProtocolParams;  
    17. import org.apache.http.protocol.HTTP;  
    18.   
    19. import android.app.Application;  
    20.   
    21. public class MyApplication extends Application {  
    22.     private HttpClient mHttpClient = null;  
    23.     private static final String CHARSET = HTTP.UTF_8;  
    24.     @Override  
    25.     public void onCreate() {  
    26.         // TODO Auto-generated method stub  
    27.         super.onCreate();  
    28.         mHttpClient = this.createHttpClient();  
    29.     }  
    30.   
    31.     @Override  
    32.     public void onTerminate() {  
    33.         // TODO Auto-generated method stub  
    34.         super.onTerminate();  
    35.         this.shutdownHttpClient();  
    36.     }  
    37.   
    38.     @Override  
    39.     public void onLowMemory() {  
    40.         // TODO Auto-generated method stub  
    41.         super.onLowMemory();  
    42.         this.shutdownHttpClient();  
    43.     }  
    44.       
    45.     /**创建HttpClient实例 
    46.      * @return 
    47.      */  
    48.     private HttpClient createHttpClient(){  
    49.         HttpParams params = new BasicHttpParams();  
    50.         //设置基本参数  
    51.         HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  
    52.         HttpProtocolParams.setContentCharset(params, CHARSET);  
    53.         HttpProtocolParams.setUseExpectContinue(params, true);  
    54.         //超时设置  
    55.         /*从连接池中取连接的超时时间*/  
    56.         ConnManagerParams.setTimeout(params, 1000);  
    57.         /*连接超时*/  
    58.         HttpConnectionParams.setConnectionTimeout(params, 2000);  
    59.         /*请求超时*/  
    60.         HttpConnectionParams.setSoTimeout(params, 4000);  
    61.         //设置HttpClient支持HTTp和HTTPS两种模式  
    62.         SchemeRegistry schReg = new SchemeRegistry();  
    63.         schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
    64.         schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));  
    65.         //使用线程安全的连接管理来创建HttpClient  
    66.         ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);  
    67.         HttpClient client = new DefaultHttpClient(conMgr, params);  
    68.         return client;  
    69.     }  
    70.     private void shutdownHttpClient(){  
    71.         if(mHttpClient != null && mHttpClient.getConnectionManager() != null){  
    72.             mHttpClient.getConnectionManager().shutdown();  
    73.         }  
    74.     }  
    75.     public HttpClient getHttpClient(){  
    76.         return mHttpClient;  
    77.     }  
    78.   
    79. }  
    80. </span>  


    然后再AndroidManifest.xml理添加:

    android:name="org.yanzi.application.MyApplication"

    1. <span style="font-family:Comic Sans MS;font-size:18px;">    <application  
    2.         android:name="org.yanzi.application.MyApplication"  
    3.         android:allowBackup="true"  
    4.         android:icon="@drawable/ic_launcher"  
    5.         android:label="@string/app_name"  
    6.         android:theme="@style/AppTheme" >  
    7.         <activity  
    8.             android:name="org.yanzi.testtomecat.MainActivity"  
    9.             android:label="@string/app_name" >  
    10.             <intent-filter>  
    11.                 <action android:name="android.intent.action.MAIN" />  
    12.   
    13.                 <category android:name="android.intent.category.LAUNCHER" />  
    14.             </intent-filter>  
    15.         </activity>  
    16.     </application></span>  


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

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

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

  • 相关阅读:
    C#基础:单例模式与多线程
    C#基础:线程同步
    C#基础:C#中的数据结构
    C#基础:GC中什么是代,一共分几代
    C#基础:Dispose方法和Finalize方法在何时被调用
    C#基础:.NET中GC的运行机制
    C#基础:简述.NET中堆栈和堆的特点和差异
    PLSQL_基础系列05_视图控制WITH CHECK OPTION(案例)
    PLSQL_基础系列04_时间间隔INTERVAL(案例)
    PLSQL_基础系列03_合并操作UNION / UNION ALL / MINUS / INTERSET(案例)
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3910811.html
Copyright © 2011-2022 走看看