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 ...
随机推荐
- 【转】iOS申请发布证书-图文详解
摘要 发布产品到App Store所需证书,2013年5月26日测试 IOS 发布证书 distribution 打包程序 真机调试证书 本文讲述发布证书的申请,申请真机调试证书请参考:http:// ...
- Swift - 16 - String.Index和Range
//: Playground - noun: a place where people can play import UIKit var str = "Welcome to Play Sw ...
- vim 支持gb2312
vi /etc/vimrc 中添加如下,并保存. set termencoding=encodingset fileencodings=utf-8,gbk,ucs-bom,cp936set shif ...
- underscorejs-indexBy学习
2.19 indexBy 2.19.1 语法 _.indexBy(list, iteratee, [context]) 2.19.2 说明 给定一个list,和 一个用来返回一个在列表中的每个元素键 ...
- Thinkphp 零散知识点(caa/js路径,引入第三方类,ajax返回,session/cookie)
一.关于JS和CSS路径问题 1.找路径是从入口文件index.php来找的,而不是从文件本身所在位置来找, 因为我们访问时是访问的入口文件 2.在存放JS和CSS的时候可以放到public文件夹下 ...
- MYSQL一对多,两表查询合并数据
select a.askid,a.title,GROUP_CONCAT(b.message SEPARATOR '----') as content from gg_ask as a join gg_ ...
- JS动态加载 js css
1.动态加载js function loadScript( url ){ var script = document.createElement( "script" ); scri ...
- 正则如何匹配div下的所有<li>标签?
<?php header('Content-Type:text/html;charset=utf-8'); $str = '<div class="c1s"> & ...
- python学习第十八天 --文件操作
这一章节主要讲解文件操作及其文件读取,缓存,文件指针. 文件操作 (1)文件打开:open(filepath,filemode) filepath:要打开文件的路径 filemode:文件打开的方式 ...
- uva 725 Division(除法)暴力法!
uva 725 Division(除法) A - 暴力求解 Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & ...