使用android-async-http来封装Android网络请求框架
2016-03-14 21:41
1106 查看
上一篇为大家讲解了如何《基于Retrofit2.0+RxJava+Dragger2实现不一样的Android网络构架搭建》 http://blog.csdn.net/finddreams/article/details/50849385
文中有谈到目前Android开发中使用的比较多的网络框架有android-async-http,Volley,OkHttp等,Retrofit2.0就是基于OkHttp的,各大网络框架都有各自的优点,今天讲的android-async-http的优点就是api调用简单,学习成本低,jar包的体积小等。
Github地址: https://github.com/loopj/android-async-http
兼容安卓API 23(6.0)和更高的版本;
库很小,jar包小于100K;
支持重试机制;
cookie的管理,内部实现用的是Android的SharedPreferences;
通过BaseJsonHttpResponseHandler和各种json库集成;
……………
BinaryHttpResponseHandler extends AsyncHttpResponseHandler ——继承AsyncHttpResponseHandler的子类,这是一个字节流返回处理的类, 该类用于处理图片,流的形式;
JsonHttpResponseHandler extends AsyncHttpResponseHandler ——继承AsyncHttpResponseHandler的子类,这是一个json请求返回处理服务器与客户端用json交流时使用的类;
AsyncHttpRequest implements Runnable ——基于线程的子类,用于 异步请求类, 通过AsyncHttpResponseHandler回调。
TextHttpResponseHandler 是把字节流转成了字符串文本的形式,方便使用;
PersistentCookieStore implements CookieStore ——这是一个基于CookieStore的子类, 使用SharedPreferences来保存Cookie数据,并具备添加清楚Cookie的功能。
RequestParams 封装了请求参数的类,是键值对的形式,相当于HashMap。有add和put方法,add方法的值只能是String,而put方法的值则可以添加很多的其他数据类型;
引入之后我们发现依赖库中不只有android-async-http:1.4.9.jar还多了一个叫httpclient 4.3.6.jar的包,这是什么原因了?
HttpClient和HttpURLConnection都很熟悉了,HttpClient 的API实现起来简单,HttpURLConnection则比较麻烦一点。Android 2.2版本之前因为HttpURLConnection存在一些bug,所以谷歌官方推荐使用HttpClient,但是后来慢慢修正了HttpURLConnection的问题, google 不再维护 HttpClient 了,以致于Android5.1里面已经把 HttpClient 标注为过期。所有Android4.0之后应该用HttpURLConnection来作为网络请求,这个想必大家都已经知道了。
所以为了修复android-async-http这个网络库对于高版本(API大于23)的android系统存在不兼容的问题,他们引入了http client这个开源的网络库,那样就可以继续使用android-async-http在Android上开发了,因为已经兼容了安卓API 23(6.0)和更高的版本,所以大可放心使用。
2.用单例模式封装一下AsyncHttpClient,方便调用管理:
client.setTimeout(SOCKET_TIMEOUT); // 设置连接超时时间,如果不设置,AsyncHttpClient默认的超时时间为为10s,如果我们的用户量过大,服务器处理请求所需要的时间比较多的话,可以增加超时时间,不要使用默认的。
setCookie()方法中新建一个PersistentCookieStore类来管理AsyncHttpClient请求中的Cookie,
PersistentCookieStore是可自动将cookie保存到Android设备的SharedPreferences中,如果你的项目中使用cookie来管理验证会话,验证请求权限的话,这个非常简单有用,因为cookie信息已经持久化在SharedPreferenceswen文件中,就算是退出了,你的登录信息还是会保持一段有效时间。
setRetry()方法中可以设置重试机制。client.setMaxRetriesAndTimeout(2, SOCKET_TIMEOUT)方法的参数一是重试的次数,第二个是重试的时间;
client.allowRetryExceptionClass(SocketTimeoutException.class)是设置出现异常的后重试的白名单,意思是当网络异常是SocketTimeoutException则可以重试。
client.blockRetryExceptionClass(SSLException.class);则是添加重试机制的黑名单,当出现SSLException异常的时候,则网络请求不会重连。
class RetryHandler implements HttpRequestRetryHandler 类的源码中,默认NoHttpResponseException,UnknownHostException,SocketException都是在白名单;而InterruptedIOException,SSLException则默认是添加在黑名单中,不会重连。
Log.i(TAG, AsyncHttpClient.getUrlWithQueryString(true, url, params));
client.getUrlWithQueryString(true, url, params)
这个方法可以把请求中的url和请求参数作为String返回,方便我们调试;比如:
文中有谈到目前Android开发中使用的比较多的网络框架有android-async-http,Volley,OkHttp等,Retrofit2.0就是基于OkHttp的,各大网络框架都有各自的优点,今天讲的android-async-http的优点就是api调用简单,学习成本低,jar包的体积小等。
概述:
android-async-http是一个基于Apache的HttpClient的异步的Android请求框架,所有的请求全在UI(主)线程之外执行,而callback成功失败的回调都是在主线程中执行。Github地址: https://github.com/loopj/android-async-http
特点:
使用HttpClient 4.3.6版本而不是Android 提供的DefaultHttpClient;兼容安卓API 23(6.0)和更高的版本;
库很小,jar包小于100K;
支持重试机制;
cookie的管理,内部实现用的是Android的SharedPreferences;
通过BaseJsonHttpResponseHandler和各种json库集成;
……………
核心类介绍:
AsyncHttpResponseHandler ——这是一个请求返回处理,成功,失败,开始,完成,等自定义处理请求的类;BinaryHttpResponseHandler extends AsyncHttpResponseHandler ——继承AsyncHttpResponseHandler的子类,这是一个字节流返回处理的类, 该类用于处理图片,流的形式;
JsonHttpResponseHandler extends AsyncHttpResponseHandler ——继承AsyncHttpResponseHandler的子类,这是一个json请求返回处理服务器与客户端用json交流时使用的类;
AsyncHttpRequest implements Runnable ——基于线程的子类,用于 异步请求类, 通过AsyncHttpResponseHandler回调。
TextHttpResponseHandler 是把字节流转成了字符串文本的形式,方便使用;
PersistentCookieStore implements CookieStore ——这是一个基于CookieStore的子类, 使用SharedPreferences来保存Cookie数据,并具备添加清楚Cookie的功能。
RequestParams 封装了请求参数的类,是键值对的形式,相当于HashMap。有add和put方法,add方法的值只能是String,而put方法的值则可以添加很多的其他数据类型;
使用方法:
1. 引入到咱们的项目中,目前的最新版本是1.4.9,解决了Android6.0以上HttpClient的不兼容问题,请使用最新的版本:compile 'com.loopj.android:android-async-http:1.4.9'
引入之后我们发现依赖库中不只有android-async-http:1.4.9.jar还多了一个叫httpclient 4.3.6.jar的包,这是什么原因了?
HttpClient和HttpURLConnection都很熟悉了,HttpClient 的API实现起来简单,HttpURLConnection则比较麻烦一点。Android 2.2版本之前因为HttpURLConnection存在一些bug,所以谷歌官方推荐使用HttpClient,但是后来慢慢修正了HttpURLConnection的问题, google 不再维护 HttpClient 了,以致于Android5.1里面已经把 HttpClient 标注为过期。所有Android4.0之后应该用HttpURLConnection来作为网络请求,这个想必大家都已经知道了。
所以为了修复android-async-http这个网络库对于高版本(API大于23)的android系统存在不兼容的问题,他们引入了http client这个开源的网络库,那样就可以继续使用android-async-http在Android上开发了,因为已经兼容了安卓API 23(6.0)和更高的版本,所以大可放心使用。
2.用单例模式封装一下AsyncHttpClient,方便调用管理:
/** * AsyncHttpClientUtils的单例 * * @Author finddreams * @Address http://blog.csdn.net/finddreams * @Time 2016/3/14 */ public class AsyncHttpClientUtils { public static final String TAG = AsyncHttpClientUtils.class.getSimpleName(); public static final int SOCKET_TIMEOUT = 20 * 1000;//默认超时时间 // public static final int DEFAULT_SOCKET_TIMEOUT = 10 * 1000; private static AsyncHttpClientUtils instance = new AsyncHttpClientUtils(); // 实例话对象 private static AsyncHttpClient client = new AsyncHttpClient(); static { // client.setConnectTimeout(SOCKET_TIMEOUT); //连接时间 // client.setResponseTimeout(SOCKET_TIMEOUT); //响应时间 client.setTimeout(SOCKET_TIMEOUT); // 设置连接超时,如果不设置,默认为10s } private PersistentCookieStore cookieStore; private AsyncHttpClientUtils() { } public static AsyncHttpClientUtils getInstance() { return instance; } public AsyncHttpClient getAsyncHttpClient() { return client; } /** * get方法带参数 */ public RequestHandle get(String url, RequestParams params, HttpCallBack httpCallBack) { Log.i(TAG, client.getUrlWithQueryString(true, url, params)); RequestHandle requestHandle = client.get(url, params, httpCallBack); return requestHandle; } /** * post请求,带参数 */ public RequestHandle post(String url, RequestParams params, HttpCallBack httpCallBack) { Log.i(TAG, client.getUrlWithQueryString(true, url, params)); RequestHandle requestHandle = client.post(url, params, httpCallBack); return requestHandle; } /** * 设置Cookie * * @param context */ public void setCookie(Context context) { cookieStore = new PersistentCookieStore(context); client.setCookieStore(cookieStore); } /** * 清楚Cookie */ public void clearSession() { if (cookieStore != null) { cookieStore.clear(); } } /** * 设置重试机制 */ public void setRetry() { client.setMaxRetriesAndTimeout(2, SOCKET_TIMEOUT); client.allowRetryExceptionClass(SocketTimeoutException.class); client.blockRetryExceptionClass(SSLException.class); } /** * 取消所有请求 * * @param context */ public void cancelAllRequests(Context context) { if (client != null) { Log.i(TAG, "cancel"); client.cancelRequests(context, true); //取消请求 client.cancelAllRequests(true); } } /* * 文件下载 * * @param paramString * @param paramBinaryHttpResponseHandler */ public void downFile(String paramString, BinaryHttpResponseHandler paramBinaryHttpResponseHandler) { try { client.get(paramString, paramBinaryHttpResponseHandler); return; } catch (IllegalArgumentException localIllegalArgumentException) { Log.d("hhxh", "URL路径不正确!!"); } } }
client.setTimeout(SOCKET_TIMEOUT); // 设置连接超时时间,如果不设置,AsyncHttpClient默认的超时时间为为10s,如果我们的用户量过大,服务器处理请求所需要的时间比较多的话,可以增加超时时间,不要使用默认的。
public static final int DEFAULT_SOCKET_TIMEOUT = 10 * 1000;
setCookie()方法中新建一个PersistentCookieStore类来管理AsyncHttpClient请求中的Cookie,
PersistentCookieStore是可自动将cookie保存到Android设备的SharedPreferences中,如果你的项目中使用cookie来管理验证会话,验证请求权限的话,这个非常简单有用,因为cookie信息已经持久化在SharedPreferenceswen文件中,就算是退出了,你的登录信息还是会保持一段有效时间。
setRetry()方法中可以设置重试机制。client.setMaxRetriesAndTimeout(2, SOCKET_TIMEOUT)方法的参数一是重试的次数,第二个是重试的时间;
client.allowRetryExceptionClass(SocketTimeoutException.class); client.blockRetryExceptionClass(SSLException.class);
client.allowRetryExceptionClass(SocketTimeoutException.class)是设置出现异常的后重试的白名单,意思是当网络异常是SocketTimeoutException则可以重试。
public static void allowRetryExceptionClass(Class<?> cls) { if (cls != null) { RetryHandler.addClassToWhitelist(cls); } }
client.blockRetryExceptionClass(SSLException.class);则是添加重试机制的黑名单,当出现SSLException异常的时候,则网络请求不会重连。
class RetryHandler implements HttpRequestRetryHandler 类的源码中,默认NoHttpResponseException,UnknownHostException,SocketException都是在白名单;而InterruptedIOException,SSLException则默认是添加在黑名单中,不会重连。
private final static HashSet<Class<?>> exceptionWhitelist = new HashSet<Class<?>>(); private final static HashSet<Class<?>> exceptionBlacklist = new HashSet<Class<?>>(); static { // Retry if the server dropped connection on us exceptionWhitelist.add(NoHttpResponseException.class); // retry-this, since it may happens as part of a Wi-Fi to 3G failover exceptionWhitelist.add(UnknownHostException.class); // retry-this, since it may happens as part of a Wi-Fi to 3G failover exceptionWhitelist.add(SocketException.class); // never retry timeouts exceptionBlacklist.add(InterruptedIOException.class); // never retry SSL handshake failures exceptionBlacklist.add(SSLException.class); }
Log.i(TAG, AsyncHttpClient.getUrlWithQueryString(true, url, params));
client.getUrlWithQueryString(true, url, params)
这个方法可以把请求中的url和请求参数作为String返回,方便我们调试;比如:
I/AsyncHttpClientUtils: http://apis.baidu.com/apistore/weatherservice/cityname?cityname=北京[/code]
3.请求的响应处理Handler 有很多种BinaryHttpResponseHandler,JsonHttpResponseHandler,TextHttpResponseHandler他们都是继承自AsyncHttpResponseHandler,TextHttpResponseHandler使用起来很简单:private TextHttpResponseHandler responseHandler = new TextHttpResponseHandler(){ @Override public void onStart() { Log.e(tag, "onStart===="); } @Override public void onSuccess(int statusCode, Header[] headers, String response) { Log.e(tag, response); } @Override public void onFailure(int statusCode, Header[] headers, String errorResponse, Throwable e) { } };
TextHttpResponseHandler直接把字节流包装成String来返回,使用起来也很方便;
4.前面说BaseJsonHttpResponseHandler 是可以集成各自json库,看到这句话,有很多人可能不知道是如何做到的,下面就是集成了Gson库的解析类:/** * 基于BaseJsonHttpResponseHandler封装的Gson泛型解析 * * @author finddreams * @address http://blog.csdn.net/finddreams */ public abstract class HttpCallBack<T> extends BaseJsonHttpResponseHandler<T> { @Override public abstract void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, T response); @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, T errorResponse) { Log.i("onFailure", throwable.getMessage()); } @Override public void onStart() { super.onStart(); } @Override public void onFinish() { super.onFinish(); } @Override public void onUserException(Throwable error) { super.onUserException(error); } @Override protected T parseResponse(String rawJsonData, boolean isFailure) throws Throwable { Log.i("rawJsonData", rawJsonData); Log.i("isFailure", isFailure + ""); T t = new Gson().fromJson(rawJsonData, getSuperclassTypeParameter(getClass())); return t; } /** * 返回gson类型 */ public static Type getSuperclassTypeParameter(Class<?> subclass) { Type superclass = subclass.getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]); } }
HttpCallBack这个类来做为请求的回调,就可以通过泛型的方式,你想把请求的结果解析成什么类就会返回什么类,这样使用起来就方便了很多。
5.最后还是用百度api提供的天气接口,来实现AsyncHttpClientget请求的调用:public class MainActivity extends AppCompatActivity { @Bind(R.id.content) EditText content; @Bind(R.id.getresult) Button getresult; @Bind(R.id.result) TextView result; public static String BaiduUrl = "http://apis.baidu.com/apistore/weatherservice/cityname"; //百度api地址 public static String baiduKey = ""; //百度申请的apikey private AsyncHttpClientUtils clientUtils; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); clientUtils = AsyncHttpClientUtils.getInstance(); } @OnClick(R.id.getresult) public void onClick(View view) { getQueryResult(); } private void getQueryResult() { RequestParams params = new RequestParams(); AsyncHttpClient client = clientUtils.getAsyncHttpClient(); client.addHeader("apikey", MainActivity.baiduKey); params.add("cityname", content.getText().toString()); RequestHandle requestHandle = clientUtils.get(BaiduUrl, params, new HttpCallBack<WeatherResultBean>() { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, WeatherResultBean response) { WeatherResultBean.RetDataEntity retData = response.getRetData(); result.setText(retData.getCity() + ":" + retData.getWeather() + ":" + retData.getDate()); } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, WeatherResultBean errorResponse) { super.onFailure(statusCode, headers, throwable, rawJsonData, errorResponse); } }); // requestHandle.cancel(true);//取消单个请求, // clientUtils.cancelAllRequests(this); //取消所有请求 } }
是不是调用起来非常的简单,不用太多的封装,非常快速的就可以完成get,post请求的调用,很适合一些中小项目的敏捷开发,而且android-async-http的jar包体积非常的小,对于apk的体积大小来说,基本上可以忽略。
同时android-async-http的api很简单,结构清晰,比较适合深入研究。还有很多实用的功能等待大家去探索,比如本文没有讲的文件上传与下载,HTTP Basic Auth身份认证等等;
最后把运行的结果图附上,调用的百度天气api接口,实现天气查询功能:
相关文章推荐
- 网络编程---(数据请求+slider)将网络上的大文件下载到本地,并打印其进度
- 复制粘贴出来的悲剧----spring实现文件下载和HttpStatus.CREATED
- Swift - 网络请求
- TCP 的那些事儿(下)
- HTTPS到底是个啥玩意儿?
- TCP 的那些事儿(上)
- 【Stanford CNN课程笔记】6.神经网络的数据预处理
- 复杂网络中聚类算法总结
- C语言中的可变参数函数 三个点“…” http://blog.chinaunix.net/uid-7283526-id-2198861.html
- php 用guzzule 6 发送HTTP请求
- FIN_WAIT_2 tcp状态多原因剖析和解决
- static_cast < type-id > ( expression ) http://blog.csdn.net/moruihong/article/details/7712260
- HTTP multipart/form-data格式之文件上传
- Volley源码学习(二):网络请求处理,HurlStack类,BasicNetwork类,ByteArrayPool,PoolingByteArrayOutputStream
- 网络编程_TCP_Socket通信_聊天室_私聊_构思_实现JAVA193-194
- 关于Eclipse使用OkHttp
- HTTP协议状态码详解
- 深入分析 Java 中的中文编码问题 (文章来自网络)
- 网络编程TCP总结及实践-C语言
- tcp简单传输过程分析