【转】 Pro Android学习笔记(七一):HTTP服务(5):多线程调用HttpClient
文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件,转载须注明出处:http://blog.csdn.net/flowingflying/
应用共享HttpClient对象的同步问题
在之前的例子中,HttpClient只用于某个请求,我们可以为整个应用创建一个共享的HttpClient对象。这就存在多线程使用的问题,而HttpClient已经考虑这个问题,只需要创建一个使用ThreadSafeClientConnManager的DefaultHttpClient对象。
创建共享HttpClient代码
创建共享对象
创建共享对象的方式是通用,如下:
public class CustomHttpClient {
private static HttpClient client = null; //应用共享的对象
/* 采用private的构造器,禁止了其他类通过CustomHttpClient xx = new CustomHttpClient();这种方式创建对象,确保对象的唯一性 */
private CustomHttpClient(){
}
/* 通过静态调用获取对象,第一次调用为空时进行创建 */
public static synchronized HttpClient getCustomHttpClient(){
if(client == null){
/*如果对象为空,创建之*/
... ...
}
return client;
}
/*禁止clone,同样也是保证对象的唯一性*/
public Object clone() throws CloneNotSupportedException{
throw new CloneNotSupportedException();
}
}
创建可共享的HttpClient对象
下面给出上面代码中省略的部分,当对象为空是,创建HttpClient对象的代码,为了方便理解,代码从可以从后往前看。
//【2.1】设置Http参数
HttpParams params = new BasicHttpParams();
/* 设置HttpParam是的基本参数,其实都是对应http请求的消息头。其中三个都很好理解,重点介绍一些setUserExpectContinue。 一般都设置为flase,设置为true通常是传递request消息很大(例携带大文件),而服务器可能需要认证,我们不希望传完这个大文件,才收到服务器的拒绝。HTTP是TCP流方式,当server收到请求的头字段是Except:100-continue, 不在等待整个请求,返回100 continue应答继续读取,或者给出拒绝请求(final Status code,如4xx)。 具体可以参考:http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3 */
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
HttpProtocolParams.setUserAgent(params, "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83)" +
" AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
/* 设置超时时间。超时的异常均属于IOException,此外ClientProtocolException也是与IOException*/
// 从ClientConnectionManager获取连接的时间,这是从连接池中获取连接的超时设置,只有在连接池所有连接都在使用的情况下才可能出现超时。超时会扔出ConnectionPoolTimeoutException。一个HttpClient对应管理器,有连接池,里面有多个连接(socket),这是我对其架构的猜测。
ConnManagerParams.setTimeout(params, 1000);
// 这是连接到远端web server的超时设置,超时会扔出ConnectTimeoutException
HttpConnectionParams.setConnectionTimeout(params, 5000);//连接超时
// 这是发送请求消息后,最多等待多长时间得到响应的设置,超时会扔出SocketTimeoutException
HttpConnectionParams.setSoTimeout(params, 10000);//socket超时
//【2.2】设置Sheme,注册了http和https
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http",PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https",PlainSocketFactory.getSocketFactory(), 443));
//【2】ClientConnectionManager用于管理HTTP连接,我们使用同一个client来处理请求,要确保多线程的使用安全,采用ThreadSafeClientConnManager,是线程安全的连接池。如果多个线程同时请求,或有延迟情况。
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg);
//【1】以ThreadSafeClientConnManager为管理器参数,创建可进行多线程调用的同步保护的HttpClient对象
client = new DefaultHttpClient(conMgr,params);
使用共享HttpClient对象的代码
基础代码
下面给出Activity调用这个共享的HttpClient的代码:
public class HttpActivity extends Activity{
private HttpClient client = null;
protected void onCreate(Bundle savedInstanceState) {
…… //UI处理等
client = CustomHttpClient.getCustomHttpClient();
getHttpContent();
}
private void getHttpContent(){
try{
HttpGet request = new HttpGet("http://www.google.com");
/* 在处理response时,利用Android提供的BasicResponseHandler:handleResponse(HttpResponse response),Returns the response body as a String. if the response was successful (a 2xx status code). */
String page = client.execute(request,new BasicResponseHandler());
Log.d("PRO-HTTP",page);
}catch(IOException e){
e.printStackTrace();
}
}
}
修改HTTP连接的参数
我们在创建HttpClient时已经设置了有关的HTTP连接参数,实际对应的是HTTP请求消息中的消息头,如果某个请求需要对这些参数进行修改,不应对公共属性进行修改,否则会影响到其他请求,而是通过对具体的request请求进行设置。代码例子如下:
// 我们设置了内部网的一个空地址,通过LogCat中连接超时出现的时间,来判断参数修改是否成功
HttpGet request = new HttpGet("http://192.168.0.199");
// 读取httpClient的参数设置
HttpParams clientParams=client.getParams();
Log.d("PRO-HTTP",Log.d(String.valueOf(HttpConnectionParams.getConnectionTimeout(clientParams)));//显示为5000
Log.d("PRO-HTTP",String.valueOf(HttpConnectionParams.getSoTimeout(clientParams)));//显示为10000
// 原来设置的连接超时是5秒,下面将重新设置该参数,设为20秒,我们将新的参数设置在request中,将不影响其他的请求
HttpParams params = request.getParams();
HttpConnectionParams.setConnectionTimeout(params, 20000);//20s
request.setParams(params);
Log.d("PRO-HTTP",String.valueOf(HttpConnectionParams.getConnectionTimeout(params)));//显示20000
Log.d("PRO-HTTP",String.valueOf(HttpConnectionParams.getSoTimeout(params))); //显示0
使用共同的Appcliation对象
对于应用全局共享同一对象,使人想起appclication对象,对于Android应用,都会有一个application对象,在在应用中可以通过getApplicationContext()或者getApplication()来获得。如果我们没有自定义的Application类,就是用android.app.Application。我们当然也可以将HttpClient对象放置在自定义的application类,但是为了这点小事来是Application类变得复杂并不可取。
在此,我们将探讨自定义的Appcliation。很简单,只要创建自定义的Application类即可,至于application对象的创建,均有系统来完成。下面我们在自定义的Application中加入一个计数器。
import android.app.Application;
public class CustomApplication extends Application{
private int counter = 0;
public int getCounter(){
return ++counter;
}
}
在应用的所有组件都都可以application对象,且是唯一的一个。从运行结果看出,获得这个对象有好几种方式。
CustomApplication app = (CustomApplication)getApplication();
Log.d("PRO-wei","counter: " + app.getCounter()); //测试一下计数器是否正常
Log.d("PRO-wei","context: " + app);
Log.d("PRO-wei","context: " + app.getApplicationContext()); //测试一下获得app类的其他方式
Log.d("PRO-wei","context: " + getApplicationContext()); //测试一下获得app类的其他方式
本博文涉及的例子代码,可以在Pro Android学习:Http service小例子中下载。
相关链接: 我的Android开发相关文章
【转】 Pro Android学习笔记(七一):HTTP服务(5):多线程调用HttpClient的更多相关文章
- 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET
目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...
- Pro Android学习笔记 ActionBar(1):Home图标区
Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...
- 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...
- 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode
目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...
- 【转】 Pro Android学习笔记(五六):配置变化
目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...
- 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式
可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...
- 【转】 Pro Android学习笔记(四二):Fragment(7):切换效果
目录(?)[-] 利用setTransition 利用setCustomAnimations 通过ObjectAnimator自定义动态效果 程序代码的编写 利用fragment transactio ...
- 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版
目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ...
- 【转】 Pro Android学习笔记(三五):Menu(6):XML方式 & PopUp菜单
目录(?)[-] 利用XML创建菜单 XML的有关属性 onClick事件 Pop-up菜单 利用XML创建菜单 在代码中对每个菜单项进行设置,繁琐且修改不灵活,不能适配多国语言的要求,可以利用资源进 ...
- 【转】 Pro Android学习笔记(三三):Menu(4):Alternative菜单
目录(?)[-] 什么是Alternative menu替代菜单 小例子说明 Alternative menu代码 关于Category和规范代码写法 关于flags 多个匹配的itemId等参数 什 ...
随机推荐
- ASP跳出FOR循环
由于ASP不能使用GOTO语句,我在FOR循环中加入一个FOR循环,若需要跳出,即退出最里面那个FOR循环. DEMO: <%dim aa = 0for i = 1 to 10 for j ...
- nginx 基础配置详解
#本文只对nginx的最基本配置项做一些解释,对于配置文件拆分管理,更详细的集群健康检查的几种方式,检查策略等在此不做详细解释了. #运行用户user nobody;#启动进程,通常设置成和cpu的数 ...
- Action三种编写方式
1. 创建普通类不实现接口与继承类 2. 实现Action接口 3. 继承ActionSupport类(常用)
- eclipse svn 分支合并到主干
最近公司产品上线,整个系统架构包含有七八个子系统,并且子系统都是集群部署.所以每次升级维护都要确保尽可能不出问题.因为整个系统刚上线不久,意味着新系统不定期有BUG需修复,但新功能模块也在持续的开发中 ...
- LeetCode:区域和检索【303】
LeetCode:区域和检索[303] 题目描述 给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点. 示例: 给定 nums = [ ...
- PAT 天梯赛 L3-001. 凑零钱 【DP】【DFS】
题目链接 https://www.patest.cn/contests/gplt/L3-001 思路 DP[I][J] I 表示第几个物品 J 表示多少钱 dp[i][j] 为 bool 值 表示 当 ...
- zabbix实现mysql数据库的监控(四)
前面介绍的内容都是用第三方开发好的插件进行mysql监控的,可能有些我们关心的监控内容并不在其中,这时一种常用的方法就是定义我们自己的脚本并将它整合到zabbix中,从而在原有监控的基础上进行有力的补 ...
- Linux电源管理(5)_Hibernate和Sleep功能介绍【转】
本文转载自:http://www.wowotech.net/pm_subsystem/std_str_func.html 1. 前言 Hibernate和Sleep两个功能是Linux Generic ...
- 剑指offer之 O(1)时间删除链表结点
问题描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. package Problem13; /* * 问题描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1 ...
- Luogu P1463 [HAOI2007]反素数ant:数学 + dfs【反素数】
题目链接:https://www.luogu.org/problemnew/show/P1463 题意: 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4. 如果某个正整数x ...