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 ...
随机推荐
- 【转】教你爱上Blocks(闭包)
Block 与传统代码相比较更加轻量,调用简洁方便,而且可以返回多个参数,使用Block可以让代码更加具有易读性,而我们在写回调时,也可以直接写在函数内部,而不用再去写一个回调函数 Block 闭包 ...
- Linux服务器指令
1.查看cpu信息:/proc/cpuinfo2.查看内存信息:/prco/meminfo3.查看服务器版本信息:cat /etc/issue4.服务器系统位数:uname -a5.网卡信息:ifco ...
- C++ 数组作为函数参数时,传递数组大小的方法
废话不多说,先上错误示范: void fun(int arr[arr_num]) { // ... } int main() { // ... int *arr = new int[10]; fun( ...
- hdu1301 Jungle Roads (Prim)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1301 依旧Prim............不多说了 #include<iostream> ...
- 试用ubuntu-12.04.3-desktop-amd64
由于工作需要,终于要开始使用大名鼎鼎的ubuntu了,从网上下了个ubuntu-12.04.3-desktop-amd64,通过vmware安装,过程相当顺利,只是装完后重启动,发现回到了命令行模式. ...
- jquery 的attr()方法解析
我想用jquery的attr()方法修改一个li小圆点的背景颜色和外边框的时候:刚开始 $("#shanghai-btn").attr({background:"#999 ...
- MyBatis学习笔记(3)—— 利用mybatis灌入假数据
由于第三方厂商未能按时提供实时数据,故需要纯手动导入一些实时数据,用于统计分析.正好最近自己学习了mybatis .因此使用mybatis 配置一个select.insert 的简单操作语句,用于灌入 ...
- Spring4.0学习笔记(7) —— 通过FactoryBean配置Bean
1.实现Spring 提供的FactoryBean接口 package com.spring.facoryBean; import org.springframework.beans.factory. ...
- weekly review
鉴于某位昔日工作在我身边的大师一直在写review,所以为了能靠近大师,我也要开始写review了. 无名师曾经说过,想要成为大师的话,要先找到一个大师,然后追随大师,再然后与大师通行,之后成为大师, ...
- 感性体验 Android 5.0 Lollipop
引言 Android5.0大概是在11月下旬开始进行OTA推送,博主手上的这台五太子(Nexus 5)也在前几天收到了Google的推送,博主当然是按耐不住赶紧FQ升级啦,但无奈的是这个大版本更新包有 ...