Android网络优化之HttpClient

本文介绍如何通过单例模式、连接管理、线程安全配置等八个方面优化Android应用中的HttpClient性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

尽管Android官网推荐在2.3及后续版本中使用HttpURLConnection作为网络开发首选类,但在连接管理 线程安全 方面,HttpClient还是具有很大优势。就目前而言,HttpClient仍是一个值得考虑的选择。对于HttpClient的优化,可以从以下几个方面着手:

    (1)采用单例模式(重用HttpClient实例)
    对于一个通信单元甚至是整个应用程序,Apache强烈推荐只使用一个HttpClient的实例。例如:

    private static HttpClient httpClient = null;

    private static synchronized HttpClient getHttpClient() {
       if(httpClient == null) {
           final HttpParams httpParams = new BasicHttpParams(); 
           httpClient = new DefaultHttpClient(httpParams);
       } 
 
      return httpClient;
    }

    (2)保持连接(重用连接)
    对于已经和服务端建立了连接的应用来说,再次调用HttpClient进行网络数据传输时,就不必重新建立新连接了,而可以重用已经建立的连接。这样无疑可以减少开销,提升速度。
    在这个方面,Apache已经做了“连接管理”,默认情况下,就会尽可能的重用已有连接,因此,不需要客户端程序员做任何配置。只是需要注意,Apache的连接管理并不会主动释放建立的连接,需要程序员在不用的时候手动关闭连接。

    (3)多线程安全管理的配置
    如果应用程序采用了多线程进行网络访问,则应该使用Apache封装好的线程安全管理类ThreadSafeClientConnManager来进行管理,这样能够更有效且更安全的管理多线程和连接池中的连接。
    (在网上也看到有人用MultiThreadedHttpConnectionManager进行线程安全管理的,后查了下Apache的API,发现MultiThreadedHttpConnectionManager是API 2.0中的类,而ThreadSafeClientConnManager是API 4.0中的类,比前者更新,所以选择使用ThreadSafeClientConnManager。另外,还看到有PoolingClientConnectionManager这个类,是API 4.2中的类,比ThreadSafeClientConnManager更新,但Android SDK中找不到该类。所以目前还是选择了ThreadSafeClientConnManager进行管理)
    例如:

    ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
    httpClient = new DefaultHttpClient(manager, httpParams);

    (4)大量传输数据时,使用“请求流/响应流”的方式
    当需要传输大量数据时,不应使用字符串(strings)或者字节数组(byte arrays),因为它们会将数据缓存至内存。当数据过多,尤其在多线程情况下,很容易造成内存溢出(out of memory,OOM)。
    而HttpClient能够有效处理“实体流(stream)”。这些“流”不会缓存至内存、而会直接进行数据传输。采用“请求流/响应流”的方式进行传输,可以减少内存占用,降低内存溢出的风险。
    例如:

    // Get method: getResponseBodyAsStream()
    // not use getResponseBody(), or getResponseBodyAsString()
    GetMethod httpGet = new GetMethod(url); 
    InputStream inputStream = httpGet.getResponseBodyAsStream();

    // Post method: getResponseBodyAsStream()
    PostMethod httpPost = new PostMethod(url); 
    InputStream inputStream = httpPost.getResponseBodyAsStream();

    (5)持续握手(Expect-continue handshake)
    在认证系统或其他可能遭到服务器拒绝应答的情况下(如:登陆失败),如果发送整个请求体,则会大大降低效率。此时,可以先发送部分请求(如:只发送请求头)进行试探,如果服务器愿意接收,则继续发送请求体。此项优化主要进行以下配置:

    // use expect-continue handshake
    HttpProtocolParams.setUseExpectContinue(httpParams, true);

    (6)“旧连接”检查(Stale connection check)
    HttpClient为了提升性能,默认采用了“重用连接”机制,即在有传输数据需求时,会首先检查连接池中是否有可供重用的连接,如果有,则会重用连接。同时,为了确保该“被重用”的连接确实有效,会在重用之前对其进行有效性检查。这个检查大概会花费15-30毫秒。关闭该检查举措,会稍微提升传输速度,但也可能出现“旧连接”过久而被服务器端关闭、从而出现I/O异常。
    关闭旧连接检查的配置为:
    // disable stale check
    HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);

    (7)超时设置
    进行超时设置,让连接在超过时间后自动失效,释放占用资源。
    // timeout: get connections from connection pool
    ConnManagerParams.setTimeout(httpParams, 1000); 
    // timeout: connect to the server
    HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
    // timeout: transfer data from server
    HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);

    (8)连接数限制
    配置每台主机最多连接数和连接池中的最多连接总数,对连接数量进行限制。其中,DEFAULT_HOST_CONNECTIONS和DEFAULT_MAX_CONNECTIONS是由客户端程序员根据需要而设置的。
    // set max connections per host
    ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_HOST_CONNECTIONS));
    // set max total connections
    ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);

    经过优化后,上一篇日志中的getHttpClient()方法代码如下:

  

  1. private static synchronized HttpClient getHttpClient() { 
  2.     if(httpClient == null) { 
  3.         final HttpParams httpParams = new BasicHttpParams();   
  4.          
  5.         // timeout: get connections from connection pool 
  6.         ConnManagerParams.setTimeout(httpParams, 1000);   
  7.         // timeout: connect to the server 
  8.         HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT); 
  9.         // timeout: transfer data from server 
  10.         HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);  
  11.          
  12.         // set max connections per host 
  13.         ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_HOST_CONNECTIONS));   
  14.         // set max total connections 
  15.         ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS); 
  16.          
  17.         // use expect-continue handshake 
  18.         HttpProtocolParams.setUseExpectContinue(httpParams, true); 
  19.         // disable stale check 
  20.         HttpConnectionParams.setStaleCheckingEnabled(httpParams, false); 
  21.          
  22.         HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);   
  23.         HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8);  
  24.            
  25.         HttpClientParams.setRedirecting(httpParams, false); 
  26.          
  27.         // set user agent 
  28.         String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6"
  29.         HttpProtocolParams.setUserAgent(httpParams, userAgent);      
  30.          
  31.         // disable Nagle algorithm 
  32.         HttpConnectionParams.setTcpNoDelay(httpParams, true);  
  33.          
  34.         HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);   
  35.          
  36.         // scheme: http and https 
  37.         SchemeRegistry schemeRegistry = new SchemeRegistry();   
  38.         schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));   
  39.         schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); 
  40.  
  41.         ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);   
  42.         httpClient = new DefaultHttpClient(manager, httpParams);  
  43.     }        
  44.      
  45.     return httpClient; 


   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值