关于开源框架Android Asynchronous Http Client的分析

来源:互联网 发布:视频播放软件 编辑:程序博客网 时间:2024/05/18 02:30

android-async-http开源框架是基于Apache HttpClient 的网络框架,可以使我们轻松的获取网络数据或者向服务器发送数据,使用起来比较简单

PS: 虽然Google官方推荐使用HttpUrlConnection(更加轻量级),但是该框架源码还是可以学习到JAVA的一些设计模式秒处,对自己设计框架很有帮助。

源码网址:https://github.com/loopj/android-async-http

大致类图

PS:暂且只列出这几个类,实际框架要复杂的多

核心类: 

AsyncHttpClient :维护一个单例DefaultHttpClient及线程池,同时可以设置各种请求的参数; 另外值得一提的是可以可以设置用GZIP压缩

提供了Http 的各种常用请求方法:head, put ,get, post, delete, 从这里看,除了可以响应RPC风格外兼容Rest风格的后台框架

核心方法:

/**     * Puts a new request in queue as a new thread in pool to be executed     *     * @param client          HttpClient to be used for request, can differ in single requests     * @param contentType     MIME body type, for POST and PUT requests, may be null     * @param context         Context of Android application, to hold the reference of request     * @param httpContext     HttpContext in which the request will be executed     * @param responseHandler ResponseHandler or its subclass to put the response into     * @param uriRequest      instance of HttpUriRequest, which means it must be of HttpDelete,     *                        HttpPost, HttpGet, HttpPut, etc.     * @return RequestHandle of future request process     */    protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) {        if (contentType != null) {            uriRequest.setHeader("Content-Type", contentType);        }        responseHandler.setRequestHeaders(uriRequest.getAllHeaders());        responseHandler.setRequestURI(uriRequest.getURI());        AsyncHttpRequest request = new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler);//创建新的请求线程        threadPool.submit(request);//提交线程        RequestHandle requestHandle = new RequestHandle(request);//使用RequestHandle(后面有简单介绍)包装request        if (context != null) {            // Add request to request map            List<RequestHandle> requestList = requestMap.get(context);            if (requestList == null) {                requestList = new LinkedList<RequestHandle>();                requestMap.put(context, requestList);            }            requestList.add(requestHandle);            Iterator<RequestHandle> iterator = requestList.iterator();            while (iterator.hasNext()) {                if (iterator.next().shouldBeGarbageCollected()) {                    iterator.remove();                }            }        }        return requestHandle;//返回对请求的引用,主要是为了可以某一时刻中止线程,查看线程状态    }


AsyncHttpRequest:继承自Runnable,封装了Http请求的基本信息

主要与ResponseHandlerInterface协作,对应调用ResponseHandlerInterface的各种sendXXXMessage()方法(如:sendStartMessage(); sendFinishMessage())

而ResponseHandler的实现类AsyncHttpResponseHandler 的sendXXXMessage方法对应调用onXXX()方法,形成回调

@Override    public void run() {        if (isCancelled()) {            return;        }        if (responseHandler != null) {            responseHandler.sendStartMessage();        }        if (isCancelled()) {            return;        }        try {            makeRequestWithRetries();        } catch (IOException e) {            if (!isCancelled() && responseHandler != null) {                responseHandler.sendFailureMessage(0, null, null, e);            } else {                Log.e("AsyncHttpRequest", "makeRequestWithRetries returned error, but handler is null", e);            }        }        if (isCancelled()) {            return;        }        if (responseHandler != null) {            responseHandler.sendFinishMessage();        }        isFinished = true;    }    private void makeRequest() throws IOException {        if (isCancelled()) {            return;        }        // Fixes #115        if (request.getURI().getScheme() == null) {            // subclass of IOException so processed in the caller            throw new MalformedURLException("No valid URI scheme was provided");        }        HttpResponse response = client.execute(request, context);        if (!isCancelled() && responseHandler != null) {            responseHandler.sendResponseMessage(response);        }    }    private void makeRequestWithRetries() throws IOException {        boolean retry = true;        IOException cause = null;        HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();        try {            while (retry) {                try {                    makeRequest();                    return;                } catch (UnknownHostException e) {                    // switching between WI-FI and mobile data networks can cause a retry which then results in an UnknownHostException                    // while the WI-FI is initialising. The retry logic will be invoked here, if this is NOT the first retry                    // (to assist in genuine cases of unknown host) which seems better than outright failure                    cause = new IOException("UnknownHostException exception: " + e.getMessage());                    retry = (executionCount > 0) && retryHandler.retryRequest(cause, ++executionCount, context);                } catch (NullPointerException e) {                    // there's a bug in HttpClient 4.0.x that on some occasions causes                    // DefaultRequestExecutor to throw an NPE, see                    // http://code.google.com/p/android/issues/detail?id=5255                    cause = new IOException("NPE in HttpClient: " + e.getMessage());                    retry = retryHandler.retryRequest(cause, ++executionCount, context);                } catch (IOException e) {                    if (isCancelled()) {                        // Eating exception, as the request was cancelled                        return;                    }                    cause = e;                    retry = retryHandler.retryRequest(cause, ++executionCount, context);                }                if (retry && (responseHandler != null)) {                    responseHandler.sendRetryMessage(executionCount);                }            }        } catch (Exception e) {            // catch anything else to ensure failure message is propagated            Log.e("AsyncHttpRequest", "Unhandled exception origin cause", e);            cause = new IOException("Unhandled exception: " + e.getMessage());        }        // cleaned up to throw IOException        throw (cause);    }


ResponseHandlerInterface: 接口,

AsyncHttpResponseHandler:抽象类,继承自ResponseHandlerInterface定义了对Http响应结果的各种回调方法, 同时该框架提拱了很丰富实现类,以后再详细分析



其他重要类:

RequestHandle:顾名思义,持有请求的句柄,含有AsyncHttpRequest实例的弱引用,用于跟踪请求执行的状态以及取消“请求”的操作(即中止线程)

RequesParams:封装了的请求参数

以下是各种类型参数的集合,使用java.util.concurrentq包提供的保证线程安全集合

各种类型的参数提供了相应有put方法

    protected ConcurrentHashMap<String, String> urlParams;//字符串参数集    protected ConcurrentHashMap<String, StreamWrapper> streamParams;//流数据集    protected ConcurrentHashMap<String, FileWrapper> fileParams;//文件集    protected ConcurrentHashMap<String, Object> urlParamsWithObjects;//对象集    protected String contentEncoding = HTTP.UTF_8;//默认编码方式UTF-8

根据useJsonStreamer标志位来决定是否使用JSON通讯方式

createMulitpartEntity()返加的HttpEntity封装了各种类型的参数,包括文件,流数据等, 

/**     * Returns an HttpEntity containing all request parameters     *     * @param progressHandler HttpResponseHandler for reporting progress on entity submit     * @return HttpEntity resulting HttpEntity to be included along with {@link     * org.apache.http.client.methods.HttpEntityEnclosingRequestBase}     * @throws IOException if one of the streams cannot be read     */    public HttpEntity getEntity(ResponseHandlerInterface progressHandler) throws IOException {        if (useJsonStreamer) {            return createJsonStreamerEntity();        } else if (streamParams.isEmpty() && fileParams.isEmpty()) {            return createFormEntity();        } else {            return createMultipartEntity(progressHandler);        }    }


RetryHandle:维护了允许请求重试的白名单与黑名单


暂时写那么多,待续....








0 0
原创粉丝点击