Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合
上文简介了HttpClient和Tomcatserver的交互,主角是HttpClient,然后它跟server交互有两种方式即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 来完毕。以下贴出完整代码:
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;
}
}
方法getSaveHttpClient()就可以获得线程安全的单例httpClient,凝视非常具体了啥都不说了,能够直接使用。
3、已经非常完美了,还能不能再优化呢?
能够使用Application来进一步优化创建HttpClient的时机及其它配置。Application的相关知识參见:链接
新建包名org.yanzi.application,在里面新建MyApplication.java,完整代码例如以下:
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;
}
}
然后再AndroidManifest.xml理加入:
android:name="org.yanzi.application.MyApplication"
<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>
然后再Activity里,通过mMyApplication = (MyApplication)getApplication();
mMyApplication.getHttpClient()得到HttpClient就能够使用了。
能够看到在Application的onCreate里就实例化了HttpClient,且在低内存和关闭时关闭连接管理器,释放资源,比2中的写到一个普通文件中更优。
相关文章
- android开机动画多长时间_Android开机动画及黑屏[通俗易懂]
- Android常用加密方式
- android okio使用方法,Android 开源框架 Okio 原理剖析「建议收藏」
- Android开发 屏幕适配之像素密度适配
- android root 缺少busybox,手机安装不了Busybox已经root安装后显示让更换路径..「建议收藏」
- android 模拟器 haxm,Android模拟器不使用HAXM
- android 获取收到短信验证码,Android自动获取短信验证码
- android scaleanimation动画,Android 的ScaleAnimation 缩放动画基本运用
- android系统中toast是什么_Android个人资料简单布局
- android进程间通信的方式_Android进程注入
- 【Android 应用开发】自定义View 和 ViewGroup
- 【Android 高性能音频】OboeTester 音频性能测试应用 ( Oboe 输出测试参数 | API 选择 | 音频输出设备选择 | 采样率 | 通道 | 采样格式 | 播放偏好 )
- 【Android 逆向】Android 逆向通用工具开发 ( 静态库项目中的网络操作核心类 CNetwork 分析 )
- 【错误记录】Android 应用安装后出现两个启动图标 ( 排查应用及依赖库中配置了 android.intent.category.LAUNCHER 的 Activity )
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( You must define ANDROID_NDK before starting. | 下载指定版本 NDK )
- 【ijkplayer】编译 Android 版本的 ijkplayer ② ( 切换到 k0.8.8 分支 | 执行 init-android.sh 脚本进行初始化操作 )
- 【错误记录】Android 中使用 Kotlin 为 EditText 组件设置文本报错 ( Type mismatch. Required:Editable. Found:String )
- 【Android NDK 开发】CMake 中查找链接 Android 自带动态库位置说明 ( ndk-bundleplatformsandroid-29arch-armusrlib )
- 【Android Gradle 插件】将自定义 Gradle 插件上传到自建 Maven 仓库 ⑥ ( 配置 Sonatype Nexus 搭建的 Maven 私服 | 配置端口号 | 配置JVM )
- 【Android Gradle 插件】Gradle 构建机制 ⑤ ( 在 Android Studio 中查看 Android Gradle 插件源码 )
- Android学习(一)详解手机开发
- android 数据存储操作之SQLite详解编程语言
- 谷歌数据恢复工具可搬迁iOS WhatsApp聊天记录至Android平台
- 浅谈Android开放网络端口的安全风险
- Android系统自带样式(android:theme)
- android滑动解锁震动效果的开启和取消
- Android调用系统的发邮件功能的小例子
- android教程之service使用方法示例详解