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 ...
随机推荐
- js bind
1.作用 函数的bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数. //bind 相比于call apply this 都等于 obj; bind是产生一个新的函数 不执 ...
- Hibernate 一对多双向关联Demo
以Classes[班级]和Student[学生]为例的Demo //Classes.java public class Classes implements Serializable { privat ...
- 使用C#连接ORACLE数据库
一.使用OracleClient组件连接Oracle .Net框架的System.Data.OracleClient.dll组件(ADO.Net组件),为连接和使用Oracle数据库提供了很大的方 ...
- Jquery学习笔记1-jquery总体代码框架
第一次在博客中记录自己的笔记,希望能坚持下去吧,加油! 今天学习的是Jquery的源代码,官网上下载,然后使用DW(dream waver)编辑器打开Js(下载的是未压缩版),版本是2.0.3.第一次 ...
- 阻塞和非阻塞socket的区别
读操作 对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返回.当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数.当s ...
- Python新手学习基础之函数-可变参数**
可变参数( ** ) 讲好了一颗*,那如果函数的最后一个参数带有 ** 前缀: 所有正常参数之外的其他的关键字参数都将被放置在一个字典中传递给函数. 要好好理解* 和 ** 两种可变参数哦~ 看个** ...
- Python Django开始
1.创建工程 C:\procedure\projects>django-admin startproject mysite 2.同步数据库 C:\procedure\projects\mysit ...
- 腾讯QQ、新浪微博等知名社交网络图标素材
腾讯QQ.新浪微博.QQ空间.淘宝.知乎.支付宝.大众点评等设计网络图标矢量素材. 注意是矢量素材,AI格式.放大缩小不变形. 社交网络图标几乎在网页制作中都会用到.一个好看的图标,完全可以提升整体网 ...
- Install RHadoop with Hadoop 2.2 – Red Hat Linux
Prerequisite Hadoop 2.2 has been installed (and the below installation steps should be applied on ea ...
- 【HDOJ】5155 Harry And Magic Box
DP.dp[i][j]可以表示i行j列满足要求的组合个数,考虑dp[i-1][k]满足条件,那么第i行的那k列可以为任意排列(2^k),其余的j-k列必须全为1,因此dp[i][j] += dp[i- ...