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

时间:2022-09-11 08:52:15

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

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

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

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

ndroid网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合的更多相关文章

  1. Android网络&lpar;4&rpar;&colon;HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合

    上文简介了HttpClient和Tomcatserver的交互,主角是HttpClient,然后它跟server交互有两种方式即get和post.所以这个HttpClient就相似于电脑上用的浏览器. ...

  2. 网络请求怎么样和UI线程交互? Activity2怎么通知Activity1 更新数据

    1.网络请求怎么样和UI线程交互? 目前我的做法是,建立线程池管理网络请求线程,通过添加task来新增网络请求.所有的网络操作通过统一的request来实现,网络返回结果通过回调onError和onS ...

  3. muduo网络库源码学习————线程安全

    线程安全使用单例模式,保证了每次只创建单个对象,代码如下: Singleton.h // Use of this source code is governed by a BSD-style lice ...

  4. java多线程&lpar;一&rpar;——线程安全的单例模式

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3. ...

  5. Android之线程安全的单例模式,Adapter注意事项之引用传值

    线程安全的单例模式单位模式一般写法如下: public static FestivalLab mInstance; private FestivalLab() { } public static Fe ...

  6. 线程安全的单例模式还需要对成员变量的set get方法设置锁么

    不需要,线程安全的单例模式,在获得对象时已经加锁了,保证每时每刻只有一个线程获得此单例对象.所以不需要再上锁了啊

  7. 从零开始构建一个Reactor模式的网络库(二)线程类Thread

    线程类Thread是对POSIX线程的封装类,因为要构建的是一个Linux环境下的多线程网络库,对线程的封装是很必要的. 首先是CurrentThread命名空间,主要是获取以及缓存线程id: #if ...

  8. 从零开始构建一个Reactor模式的网络库(一) 线程同步Mutex和Condition

    最近在学习陈硕大神的muduo库,感觉写的很专业,以及有一些比较“高级”的技巧和设计方式,自己写会比较困难. 于是打算自己写一个简化版本的Reactor模式网络库,就取名叫mini吧,同样只基于Lin ...

  9. android和网络连接相关的类URL,URLConnection,HttpURLConnection,HttpClient

    这几个类都是用于和服务器端的连接,有些功能都能够实现,关系是: 一.URL URL标识着网络上的一个资源:该类包含一些URL自身的方法,如获取URL对应的主机名称,端口号,协议,查询字符串外,还有些方 ...

随机推荐

  1. 【腾讯Bugly干货分享】微信小程序开发思考总结——腾讯&OpenCurlyDoubleQuote;信用卡还款”项目实践

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/58212d0fa7a7574c4f4cc3c5 作者:peggy 小程序概述 1 ...

  2. Spring MVC 学习总结(二)——控制器定义与&commat;RequestMapping详解

    一.控制器定义 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现. 控制器解析用户的请求并将其转换为一个模型.在Spring MVC中一个控制器可以包含多个Action(动作. ...

  3. UIScrollView增加刷新

    1. if (!self.scrollView) { CGRect frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.frame), CGRe ...

  4. Windows下安装MinGW,编译c&sol;c&plus;&plus;时出现cannot find -lpthread解决办法

    由于Mingw下没有带pthread库,所以在eclipse中设置多线程动态链接库,也不管用.需要自己下载, ftp://sourceware.org/pub/pthreads-win32/pthre ...

  5. php网页,想弹出对话框, 消息框 简单代码

    php网页,想弹出对话框, 消息框 简单代码 <?php echo "<script language=\"JavaScript\">alert(\&q ...

  6. 揭开枚举类的面纱(Unlocking the Enumeration&sol;enum Mystery)

    枚举给用户定义固定数据组提供了方便.枚举类就是一系列常量整型值,这也就意味着枚举类型不能被修改. 这里我们将要讨论C语言中枚举类型的用法和限制. 枚举通过枚举关键值定义,类似结构体定义 语法(Synt ...

  7. 用java代码作日历

    import java.util.Calendar; public class CalendarBean { String day[]; int year=2005,month=0; public v ...

  8. Puppeteer - 谷歌推出的自动化测试工具库

    Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制无头 Chrome 或 Chromium.它允许你从浏览器之外的环境(即命令行)与Chromium ...

  9. windows下使用vscode编写运行以及调试C&sol;C&plus;&plus;

    未经允许,禁止转载,唯一出处:tangming博客园 最后更新于2019年4月4日: 多次更新,内容较多,篇幅较大,但如果是喜欢visual stdio code这款编辑器的话建议仔细阅读,有疑问的地 ...

  10. 如何在chrome上打开SSL3&period;0

    Chrome默认关闭对SSL3.0的支持,无法访问一些Web应用.可以手动打开他. 启动chrome依次选择 设置->高级->系统->打开代理设置->安全 将使用SSL 3.0 ...