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中的写到一个普通文件里更优。

  • 相关阅读:
    数学+高精度 ZOJ 2313 Chinese Girls' Amusement
    最短路(Bellman_Ford) POJ 1860 Currency Exchange
    贪心 Gym 100502E Opening Ceremony
    概率 Gym 100502D Dice Game
    判断 Gym 100502K Train Passengers
    BFS POJ 3278 Catch That Cow
    DFS POJ 2362 Square
    DFS ZOJ 1002/HDOJ 1045 Fire Net
    组合数学(全排列)+DFS CSU 1563 Lexicography
    stack UVA 442 Matrix Chain Multiplication
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3910811.html
Copyright © 2011-2022 走看看