打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android开源项目xUtils HttpUtils模块分析
分类: android 2014-04-20 20:32 2405人阅读 评论(0) 收藏 举报

xUtils是github上的一个Android开源工具项目,其中HttpUtils模块是处理网络连接部分,刚好最近想整理下Android网络编程知识,今天学习下xUtils中HttpUtils.

xUtils项目地址:https://github.com/wyouflf/xUtils

先看看分析的时序图,了解下基本的过程



1. Activity创建HttpUtils对象

  1. HttpUtils http = new HttpUtils();  

查看HttpUtils类的构造函数

  1. public HttpUtils() {  
  2.        this(HttpUtils.DEFAULT_CONN_TIMEOUT);  
  3.    }  
  4.   
  5.    public HttpUtils(int connTimeout) {  
  6.        HttpParams params = new BasicHttpParams();  
  7.   
  8.        ConnManagerParams.setTimeout(params, connTimeout);  
  9.        HttpConnectionParams.setSoTimeout(params, connTimeout);  
  10.        HttpConnectionParams.setConnectionTimeout(params, connTimeout);  
  11.   
  12.        ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(10));  
  13.        ConnManagerParams.setMaxTotalConnections(params, 10);  
  14.   
  15.        HttpConnectionParams.setTcpNoDelay(params, true);  
  16.        HttpConnectionParams.setSocketBufferSize(params, 1024 * 8);  
  17.        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  
  18.   
  19.        SchemeRegistry schemeRegistry = new SchemeRegistry();  
  20.        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
  21.        schemeRegistry.register(new Scheme("https", DefaultSSLSocketFactory.getSocketFactory(), 443));  
  22.   
  23.        httpClient = new DefaultHttpClient(<span style="font-family: Arial, Helvetica, sans-serif;">new ThreadSafeClientConnManager(params, schemeRegistry)</span>, params);  
  24.   
  25.        httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_RETRY_TIMES));  
  26.   
  27.        httpClient.addRequestInterceptor(new HttpRequestInterceptor() {  
  28.            @Override  
  29.            public void process(org.apache.http.HttpRequest httpRequest, HttpContext httpContext) throws org.apache.http.HttpException, IOException {  
  30.                if (!httpRequest.containsHeader(HEADER_ACCEPT_ENCODING)) {  
  31.                    httpRequest.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);  
  32.                }  
  33.            }  
  34.        });  
  35.   
  36.        httpClient.addResponseInterceptor(new HttpResponseInterceptor() {  
  37.            @Override  
  38.            public void process(HttpResponse response, HttpContext httpContext) throws org.apache.http.HttpException, IOException {  
  39.                final HttpEntity entity = response.getEntity();  
  40.                if (entity == null) {  
  41.                    return;  
  42.                }  
  43.                final Header encoding = entity.getContentEncoding();  
  44.                if (encoding != null) {  
  45.                    for (HeaderElement element : encoding.getElements()) {  
  46.                        if (element.getName().equalsIgnoreCase("gzip")) {  
  47.                            response.setEntity(new GZipDecompressingEntity(response.getEntity()));  
  48.                            return;  
  49.                        }  
  50.                    }  
  51.                }  
  52.            }  
  53.        });  
  54.    }  

这里主要是设置HttpParams参数,然后创建httpClient对象。

注意这个类ThreadSafeClientConnManager,它主要是为了使用线程安全的连接管理来创建HttpClient。

不过这里就有个疑问了,之前看资料了解到一般创建HttpClient都是用的 单例模式,说是一个httpClient就相当于是一个小型的浏览器,如果创建多个httpClient就很消耗资源了,我看了这个开源项目给的demo,是创建一个请求就创建一个HttpClient, 到时跟作者联系看看是什么回事。


2.发送请求

  1.  http.send(HttpRequest.HttpMethod.GET,  
  2.                 "http://www.baidu.com",  
  3.                 new RequestCallBack<String>() {  
  4.   
  5.   
  6.                     @Override  
  7.                     public void onStart() {  
  8.                         resultText.setText("conn...");  
  9.                     }  
  10.   
  11.   
  12.                     @Override  
  13.                     public void onLoading(long total, long current, boolean isUploading) {  
  14.                         resultText.setText(current + "/" + total);  
  15.                     }  
  16.   
  17.   
  18.                     @Override  
  19.                     public void onSuccess(ResponseInfo<String> responseInfo) {  
  20.                         resultText.setText("response:" + responseInfo.result);  
  21.                     }  
  22.   
  23.   
  24.   
  25.   
  26.                     @Override  
  27.                     public void onFailure(HttpException error, String msg) {  
  28.                         resultText.setText(msg);  
  29.                     }  
  30.                 });  

调用send方法发生请求,

HttpRequest.HttpMethod.GET指明请求的方式,

"http://www.baidu.com"请求的地址,

new RequestCallBack<String>()请求的回调函数,这里面四个方法方便开发者处理请求的各个阶段的结果。


3. http.send()

  1.   
  1. public <T> HttpHandler<T> send(HttpRequest.HttpMethod method, String url,  
  2.                                RequestCallBack<T> callBack) {  
  3.     return send(method, url, null, callBack);  
  4. }  
  5.   
  6. public <T> HttpHandler<T> send(HttpRequest.HttpMethod method, String url, RequestParams params,  
  7.                                RequestCallBack<T> callBack) {  
  8.     if (url == nullthrow new IllegalArgumentException("url may not be null");  
  9.   
  10.     HttpRequest request = new HttpRequest(method, url);  
  11.     return sendRequest(request, params, callBack);  
  12. }  
  13. private <T> HttpHandler<T> sendRequest(HttpRequest request, RequestParams params, RequestCallBack<T> callBack) {  
  14.   
  15.     HttpHandler<T> handler = new HttpHandler<T>(httpClient, httpContext, responseTextCharset, callBack);  
  16.   
  17.     handler.setExpiry(currentRequestExpiry);  
  18.     handler.setHttpRedirectHandler(httpRedirectHandler);  
  19.     request.setRequestParams(params, handler);  
  20.   
  21.     handler.executeOnExecutor(executor, request);  
  22.     return handler;  
  23. }  

查看httpUtils的send函数,发现最后会调用sendRequest函数

在sendRequest里创建HttpHandler对象

4. HttpHandler

  1. HttpHandler<T> extends CompatibleAsyncTask<Object, Object, Void> implements RequestCallBackHandler  


参看httpHandler发现它继承CompatibleAsyncTask


5.CompatibleAsyncTask

查看CompatibleAsyncTask ,发现它是A compatible AsyncTask for android2.2.你懂得


6.handler.executeOnExecutor(executor, request)

在第3步里创建完httpHandler后,调用handler.executeOnExecutor(executor, request),而通过第4步了解到httpHandler继承CompatiableAsyncTask, 就先去看看doInBackground里做了什么事情。


7.doInBackground(Object... params)

  1.             //先处理传递进来的params  
  2.               
  3.             this.publishProgress(UPDATE_START);  
  4.   
  5.   
  6.             lastUpdateTime = SystemClock.uptimeMillis();  
  7.   
  8.   
  9.             ResponseInfo<T> responseInfo = sendRequest(request);  
  10.             if (responseInfo != null) {  
  11.                 this.publishProgress(UPDATE_SUCCESS, responseInfo);  
  12.                 return null;  
  13.             }  
先处理传递进来的params,调用publishProgress更新下当前的状态,然后调用sendRequest


8.sendRequest(HttpRequestBase request)

  1.   private ResponseInfo<T> sendRequest(HttpRequestBase request) throws HttpException {  
  2.   
  3.   
  4.         HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();  
  5.         while (true) {  
  6.   
  7.                 requestMethod = request.getMethod();  
  8.                 if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {  
  9.                     String result = HttpUtils.sHttpCache.get(requestUrl);  
  10.                     if (result != null) {  
  11.                         return new ResponseInfo<T>(null, (T) result, true);  
  12.                     }  
  13.                 }  
  14.   
  15.   
  16.                 ResponseInfo<T> responseInfo = null;  
  17.                 if (!isCancelled()) {  
  18.                     HttpResponse response = client.execute(request, context);  
  19.                     responseInfo = handleResponse(response);  
  20.                 }  
  21.                 return responseInfo;  
  22.             } catch (Exception e) {  
  23.                 exception = e;  
  24.                 retry = retryHandler.retryRequest(exception, ++retriedCount, context);  
  25.             }   
  26.             if (!retry) {  
  27.                 throw new HttpException(exception);  
  28.             }  
  29.         }  
  30.     }  
这个方法仔细看看,

先获取下client.getHttpRequestRetryHandler(),获取retry的设置

  1. requestMethod = request.getMethod();  
  2.                 if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {  
  3.                     String result = HttpUtils.sHttpCache.get(requestUrl);  
  4.                     if (result != null) {  
  5.                         return new ResponseInfo<T>(null, (T) result, true);  
  6.                     }  
  7.                 }  
如果使用了缓存则通过requestUrl去httpCache去获取,获取到了则创建ResponseInfo对象


如果没有缓存

  1. HttpResponse response = client.execute(request, context);  
  2.                     responseInfo = handleResponse(response);  

调用httpClient执行http请求,获取到得结果交由handleResponse处理


如果之前的处理出现异常则

  1. retry = retryHandler.retryRequest(exception, ++retriedCount, context);  

调用retry机制,直到有结果,或者超过retry的次数


9.handleResponse()

第8步的时候,如果client执行获取到结果则调用handleResponse(HttpResponse response)处理结果

  1. ResponseInfo<T> handleResponse(HttpResponse response) throws HttpException, IOException {  
  2.   
  3.        StatusLine status = response.getStatusLine();  
  4.        int statusCode = status.getStatusCode();  
  5.        if (statusCode < 300) {  
  6.    
  7.                    result = mStringDownloadHandler.handleEntity(entity, this, charset);  
  8.                    if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {  
  9.                        HttpUtils.sHttpCache.put(requestUrl, (String) result, expiry);  
  10.                    }  
  11.                  
  12.            }  
  13.            return new ResponseInfo<T>(response, (T) result, false);  
  14.        } else if (statusCode == 301 || statusCode == 302) {  
  15.            if (httpRedirectHandler == null) {  
  16.                httpRedirectHandler = new DefaultHttpRedirectHandler();  
  17.            }  
  18.            HttpRequestBase request = httpRedirectHandler.getDirectRequest(response);  
  19.            if (request != null) {  
  20.                return this.sendRequest(request);  
  21.            }  
  22.        }   
  23.        return null;  
  24.    }  
这个方法主要根据返回的statuscode处理,<300将结果存在HttpCache里,301或者302则处理重定向

10.publishProgress(UPDATE_SUCCESS, responseInfo)

在获得ResponseInfo后,调用 publishProgress(UPDATE_SUCCESS, responseInfo)方法,最后会调用onProgressUpdate方法

  1. protected void onProgressUpdate(Object... values) {  
  2.             case UPDATE_SUCCESS:  
  3.                 if (values.length != 2return;  
  4.                 this.state = State.SUCCESS;  
  5.                 callback.onSuccess((ResponseInfo<T>) values[1]);  
  6.                 break;  
  7.             default:  
  8.                 break;  
  9.         }  
  10.     }  
这onProgressUpdate里发现最终调用第2步传进来的callback


整个的调用过程基本上是这样。

1.创建httputils时创建httpClient,调用send发送请求

2. 调用send时,创建httpHandler,此类继承CompatibleAsyncTask

3.在httpHandler的doInBackground真正的处理http请求,此时会判断是否有缓存,获取结果后,通过回调处理结果


  1.   








1
0
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android开发框架xUtils
Xutils的使用
Android Post Get(最新 HttpClient 事例)
打造Android的中文Siri语音助手(一)
Android内存泄露实践分析
《Android项目式程序设计》12 网络编程写字字帖
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服