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

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

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



1. Activity创建HttpUtils对象

HttpUtils http = new HttpUtils();

查看HttpUtils类的构造函数

 public HttpUtils() {        this(HttpUtils.DEFAULT_CONN_TIMEOUT);    }    public HttpUtils(int connTimeout) {        HttpParams params = new BasicHttpParams();        ConnManagerParams.setTimeout(params, connTimeout);        HttpConnectionParams.setSoTimeout(params, connTimeout);        HttpConnectionParams.setConnectionTimeout(params, connTimeout);        ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(10));        ConnManagerParams.setMaxTotalConnections(params, 10);        HttpConnectionParams.setTcpNoDelay(params, true);        HttpConnectionParams.setSocketBufferSize(params, 1024 * 8);        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);        SchemeRegistry schemeRegistry = new SchemeRegistry();        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));        schemeRegistry.register(new Scheme("https", DefaultSSLSocketFactory.getSocketFactory(), 443));        httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(params, schemeRegistry), params);        httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_RETRY_TIMES));        httpClient.addRequestInterceptor(new HttpRequestInterceptor() {            @Override            public void process(org.apache.http.HttpRequest httpRequest, HttpContext httpContext) throws org.apache.http.HttpException, IOException {                if (!httpRequest.containsHeader(HEADER_ACCEPT_ENCODING)) {                    httpRequest.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);                }            }        });        httpClient.addResponseInterceptor(new HttpResponseInterceptor() {            @Override            public void process(HttpResponse response, HttpContext httpContext) throws org.apache.http.HttpException, IOException {                final HttpEntity entity = response.getEntity();                if (entity == null) {                    return;                }                final Header encoding = entity.getContentEncoding();                if (encoding != null) {                    for (HeaderElement element : encoding.getElements()) {                        if (element.getName().equalsIgnoreCase("gzip")) {                            response.setEntity(new GZipDecompressingEntity(response.getEntity()));                            return;                        }                    }                }            }        });    }

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

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

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


2.发送请求

 http.send(HttpRequest.HttpMethod.GET,                "http://www.baidu.com",                new RequestCallBack() {                    @Override                    public void onStart() {                        resultText.setText("conn...");                    }                    @Override                    public void onLoading(long total, long current, boolean isUploading) {                        resultText.setText(current + "/" + total);                    }                    @Override                    public void onSuccess(ResponseInfo responseInfo) {                        resultText.setText("response:" + responseInfo.result);                    }                    @Override                    public void onFailure(HttpException error, String msg) {                        resultText.setText(msg);                    }                });

调用send方法发生请求,

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

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

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


3. http.send()

    public  HttpHandler send(HttpRequest.HttpMethod method, String url,                                   RequestCallBack callBack) {        return send(method, url, null, callBack);    }    public  HttpHandler send(HttpRequest.HttpMethod method, String url, RequestParams params,                                   RequestCallBack callBack) {        if (url == null) throw new IllegalArgumentException("url may not be null");        HttpRequest request = new HttpRequest(method, url);        return sendRequest(request, params, callBack);    }    private  HttpHandler sendRequest(HttpRequest request, RequestParams params, RequestCallBack callBack) {        HttpHandler handler = new HttpHandler(httpClient, httpContext, responseTextCharset, callBack);        handler.setExpiry(currentRequestExpiry);        handler.setHttpRedirectHandler(httpRedirectHandler);        request.setRequestParams(params, handler);        handler.executeOnExecutor(executor, request);        return handler;    }

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

在sendRequest里创建HttpHandler对象

4. HttpHandler

HttpHandler extends CompatibleAsyncTask 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)

            //先处理传递进来的params                        this.publishProgress(UPDATE_START);            lastUpdateTime = SystemClock.uptimeMillis();            ResponseInfo responseInfo = sendRequest(request);            if (responseInfo != null) {                this.publishProgress(UPDATE_SUCCESS, responseInfo);                return null;            }
先处理传递进来的params,调用publishProgress更新下当前的状态,然后调用sendRequest


8.sendRequest(HttpRequestBase request)

  private ResponseInfo sendRequest(HttpRequestBase request) throws HttpException {        HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();        while (true) {                requestMethod = request.getMethod();                if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {                    String result = HttpUtils.sHttpCache.get(requestUrl);                    if (result != null) {                        return new ResponseInfo(null, (T) result, true);                    }                }                ResponseInfo responseInfo = null;                if (!isCancelled()) {                    HttpResponse response = client.execute(request, context);                    responseInfo = handleResponse(response);                }                return responseInfo;            } catch (Exception e) {                exception = e;                retry = retryHandler.retryRequest(exception, ++retriedCount, context);            }             if (!retry) {                throw new HttpException(exception);            }        }    }
这个方法仔细看看,

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

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


如果没有缓存

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

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


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

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

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


9.handleResponse()

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

 ResponseInfo handleResponse(HttpResponse response) throws HttpException, IOException {        StatusLine status = response.getStatusLine();        int statusCode = status.getStatusCode();        if (statusCode < 300) {                      result = mStringDownloadHandler.handleEntity(entity, this, charset);                    if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {                        HttpUtils.sHttpCache.put(requestUrl, (String) result, expiry);                    }                            }            return new ResponseInfo(response, (T) result, false);        } else if (statusCode == 301 || statusCode == 302) {            if (httpRedirectHandler == null) {                httpRedirectHandler = new DefaultHttpRedirectHandler();            }            HttpRequestBase request = httpRedirectHandler.getDirectRequest(response);            if (request != null) {                return this.sendRequest(request);            }        }         return null;    }
这个方法主要根据返回的statuscode处理,<300将结果存在HttpCache里,301或者302则处理重定向

10.publishProgress(UPDATE_SUCCESS, responseInfo)

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

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


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

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

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

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


   








更多相关文章

  1. Android(安卓)Intent 其中一个分析
  2. android developer API Guider之user interface---Settings(二)
  3. 传统menu的使用方法总结
  4. 理解---Android(安卓)向右滑动销毁(finish)Activity, 随着手势的滑
  5. Android客户端三步完成支付宝支付SDK接入
  6. Android(安卓)AIDL的实现
  7. android实现session保持
  8. Android在绘制View之前计算其高度 / 宽度
  9. Android(安卓)Studio配置百度地图开发环境

随机推荐

  1. Activity属性
  2. Android Log 机制
  3. android studio中用svn来管理项目
  4. Android--ListView滚动条样式
  5. ok6410 android driver(5)
  6. Android新技术
  7. Android中使用Kotlin实现一个简单的登录
  8. Android官方架构组件介绍之LifeCycle
  9. [android]fmodex在某些android设备上声音
  10. Android学习07-----事件处理(4)键盘事件