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 ...
随机推荐
- ORACLE_DBA管理脚本
SYS @ prod >col index_name for a10 SYS @ prod >col table_name for a10 SYS @ prod >col start ...
- Xcode快捷键 (本人总结常用的)
以下分类显示最常用的快捷键: 1. 文件 CMD + N: 新文件 CMD + SHIFT + N: 新项目 CMD + O: 打开 CMD + S: 保存 CMD + SHIFT + S: ...
- Building,Packaging,Deploying,and Administering Applications and Types
在我们进入章节之前,我们讨论一下生成.打包和部署你的应用程序和应用程序类型必须的步骤.在这章里,我关注的是如何为你的应用程序的用途生成程序集.在第三章,"共享程序集合和强命名程序集" ...
- hdu 1548 A strange lift (bfs)
A strange lift Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- jquery easy ui 学习 (1)Basic Window
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- UI基础 - UITabBarController
self.window = [[UIWindow alloc] init]; self.window.frame = [UIScreen mainScreen].bounds; oneViewCont ...
- block 高级
//从后往前传值 声明block属性 //copy 目的是 将栈区的block拷贝一份到堆区 @property(nonatomic,copy)void (^sendValueBlock)(id); ...
- spring 日志
spring日志结构
- 《30天自制操作系统》读书笔记(2)hello, world
让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实 ...
- pojPots
http://poj.org/problem?id=3414 #include<cstdio> #include<cstring> #define MAXN 1000000 u ...