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 来完成。下面贴出完整代码:
- <span style="font-family:Comic Sans MS;font-size:18px;">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;
- }
- }
- </span>
方法getSaveHttpClient()即可获得线程安全的单例httpClient,注释很详细了啥都不说了,可以直接使用。
3、已经很完美了,还能不能再优化呢?
可以使用Application来进一步优化创建HttpClient的时机及其他配置。Application的相关知识参见:链接
新建包名org.yanzi.application,在里面新建MyApplication.java,完整代码如下:
- <span style="font-family:Comic Sans MS;font-size:18px;">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;
- }
- }
- </span>
然后再AndroidManifest.xml理添加:
android:name="org.yanzi.application.MyApplication"
- <span style="font-family:Comic Sans MS;font-size:18px;"> <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></span>
然后再Activity里,通过mMyApplication = (MyApplication)getApplication();
mMyApplication.getHttpClient()得到HttpClient就可以使用了。
可以看到在Application的onCreate里就实例化了HttpClient,且在低内存和关闭时关闭连接管理器,释放资源,比2中的写到一个普通文件里更优。
ndroid网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合的更多相关文章
- Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合
上文简介了HttpClient和Tomcatserver的交互,主角是HttpClient,然后它跟server交互有两种方式即get和post.所以这个HttpClient就相似于电脑上用的浏览器. ...
- 网络请求怎么样和UI线程交互? Activity2怎么通知Activity1 更新数据
1.网络请求怎么样和UI线程交互? 目前我的做法是,建立线程池管理网络请求线程,通过添加task来新增网络请求.所有的网络操作通过统一的request来实现,网络返回结果通过回调onError和onS ...
- muduo网络库源码学习————线程安全
线程安全使用单例模式,保证了每次只创建单个对象,代码如下: Singleton.h // Use of this source code is governed by a BSD-style lice ...
- java多线程(一)——线程安全的单例模式
概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3. ...
- Android之线程安全的单例模式,Adapter注意事项之引用传值
线程安全的单例模式单位模式一般写法如下: public static FestivalLab mInstance; private FestivalLab() { } public static Fe ...
- 线程安全的单例模式还需要对成员变量的set get方法设置锁么
不需要,线程安全的单例模式,在获得对象时已经加锁了,保证每时每刻只有一个线程获得此单例对象.所以不需要再上锁了啊
- 【多线程那些事儿】如何使用C++写一个线程安全的单例模式?
如何写一个线程安全的单例模式? 单例模式的简单实现 单例模式大概是流传最为广泛的设计模式之一了.一份简单的实现代码大概是下面这个样子的: class singleton { public: stati ...
- 从零开始构建一个Reactor模式的网络库(二)线程类Thread
线程类Thread是对POSIX线程的封装类,因为要构建的是一个Linux环境下的多线程网络库,对线程的封装是很必要的. 首先是CurrentThread命名空间,主要是获取以及缓存线程id: #if ...
- 从零开始构建一个Reactor模式的网络库(一) 线程同步Mutex和Condition
最近在学习陈硕大神的muduo库,感觉写的很专业,以及有一些比较“高级”的技巧和设计方式,自己写会比较困难. 于是打算自己写一个简化版本的Reactor模式网络库,就取名叫mini吧,同样只基于Lin ...
随机推荐
- 安装php时,make步骤报错make: *** [ext/gd/gd.lo] Error 1
安装PHP时,make步骤报错make: *** [ext/gd/gd.lo] Error 1 /usr/local/src/LAMP+memcahed+catci/php-5.4.0/ext/gd/ ...
- jrae源码解析(二)
本文细述上文引出的RAECost和SoftmaxCost两个类. SoftmaxCost 我们已经知道,SoftmaxCost类在给定features和label的情况下(超参数给定),衡量给定权重( ...
- 直接拿来用的15个jQuery代码片段
1.预加载图片 1 2 3 4 5 6 7 8 9 10 11 12 (function($) { var cache = []; // Arguments are image paths r ...
- 【转】iOS开发系列--数据存取
原文: http://www.cnblogs.com/kenshincui/p/4077833.html#SQLite 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储 ...
- git在windows常用命令
git add * git commit(会自动打开一个文本文档让你写提交注释),若是不好用可以用 git commit -m "注释" git push
- C# ,asp.net 获取当前,相对,绝对路径(转)
C# ,asp.net 获取当前,相对,绝对路径 一.C#获取当前路径的方法: . System.Diagnostics.Process.GetCurrentProcess().MainModule. ...
- 插入数据显示 Duplicate entry '4913' for key 'user_id'
提示信息翻译:插入4913 使索引重复 分析:索引如果是primary unique这两两种,那么数据表的数据对应的这个字段就必须保证其每条记录的唯一性.否则就会产生这个错误. 一般发生在对数据库写操 ...
- Python文件处理之文件指针(四)
当我们读取文件内容时,并不能重复的读取,比如一个blogCblog.txt文件里有blogCblog内容,用两个read()方法读取blogCblog.txt的内容,会发现,第一个返回文件内容,第二个 ...
- Tomcat基础教程(一)
Tomcat, 是Servlet和JSP容器,其是实现了JSP规范的servlet容器.它在servlet生命周期内包容,装载,运行,和停止servlet容器. Servlet容器的三种工作模式: 1 ...
- Solr4.8.0源码分析(9)之Lucene的索引文件(2)
Solr4.8.0源码分析(9)之Lucene的索引文件(2) 一. Segments_N文件 一个索引对应一个目录,索引文件都存放在目录里面.Solr的索引文件存放在Solr/Home下的core/ ...