黑马程序员技术交流社区

标题: 【框架解读】android-async-http-master 源码解读 [打印本页]

作者: Android_Robot    时间: 2016-5-5 09:45
标题: 【框架解读】android-async-http-master 源码解读
本帖最后由 Android_Robot 于 2016-10-26 15:16 编辑


先介绍一下android-async-http-master。这个是安卓上的一个开源项目 ,这个网络请求库是基于Apache HttpClient库之上的一个异步网络请求处理库,网络处理均基于Android的非UI线程,通过回调方法处理请求结果。


使用方法:

先将项目内年jar包引用到工程中。然后将项目 中com.loopj.android.http放到工程中,然后就可以使用了。一开始的时候不知道。还是弄了一会儿才发现还得copy一个包进来 。

工程调试好之后运行工程。这个开源项目 自带了一个如何调用接口的一个demo。


效果如图

里面包括了在开发中常用的几种网络请求类型。  


  1. @Override  
  2. protected void onListItemClick(ListView l, View v, int position, long id) {  
  3.     Class<?> targetClass;  
  4.     switch (position) {  
  5.     case 0:  
  6.     default:  
  7.         targetClass = GetSample.class;  
  8.         break;  
  9.     case 1:  
  10.         targetClass = PostSample.class;  
  11.         break;  
  12.     case 2:  
  13.         targetClass = DeleteSample.class;  
  14.         break;  
  15.     case 3:  
  16.         targetClass = PutSample.class;  
  17.         break;  
  18.     case 4:  
  19.         targetClass = JsonSample.class;  
  20.         break;  
  21.     case 5:  
  22.         targetClass = FileSample.class;  
  23.         break;  
  24.     case 6:  
  25.         targetClass = BinarySample.class;  
  26.         break;  
  27.     case 7:  
  28.         targetClass = ThreadingTimeoutSample.class;  
  29.         break;  
  30.     case 8:  
  31.         targetClass = CancelAllRequestsSample.class;  
  32.         break;  
  33.     case 9:  
  34.         targetClass = CancelRequestHandleSample.class;  
  35.         break;  
  36.     case 10:  
  37.         targetClass = SynchronousClientSample.class;  
  38.         break;  
  39.     }  
  40.     if (targetClass != null)  
  41.         startActivity(new Intent(this, targetClass));  
  42. }
复制代码

在主界面中通过实现onListItemClick()方法调用各个示例类。这个编码风格很好。

先看最常用的get例子

执行一下get操作


getsample代码如下

  1. <span style="line-height: 1.5;">package com.loopj.android.http.sample;  </span>  
  2. import org.apache.http.Header;  
  3. import org.apache.http.HttpEntity;  
  4.   
  5. import android.util.Log;  
  6.   
  7. import com.loopj.android.http.AsyncHttpClient;  
  8. import com.loopj.android.http.AsyncHttpResponseHandler;  
  9. import com.loopj.android.http.RequestHandle;  
  10. import com.loopj.android.http.ResponseHandlerInterface;  
  11.   
  12. public class GetSample extends SampleParentActivity {  
  13.     private static final String LOG_TAG = "GetSample";  
  14.   
  15.     @Override  
  16.     public RequestHandle executeSample(AsyncHttpClient client, String URL, Header[] headers, HttpEntity entity, ResponseHandlerInterface responseHandler) {  
  17.         return client.get(this, URL, headers, null, responseHandler);  
  18.     }  
  19.   
  20.     @Override  
  21.     public int getSampleTitle() {  
  22.         return R.string.title_get_sample;  
  23.     }  
  24.   
  25.     @Override  
  26.     public boolean isRequestBodyAllowed() {  
  27.         return false;  
  28.     }  
  29.   
  30.     @Override  
  31.     public boolean isRequestHeadersAllowed() {  
  32.         return true;  
  33.     }  
  34.   
  35.     @Override  
  36.     public String getDefaultURL() {  
  37.         return "https://httpbin.org/get";  
  38.     }  
  39.   
  40.     @Override  
  41.     public ResponseHandlerInterface getResponseHandler() {  
  42.         return new AsyncHttpResponseHandler() {  
  43.   
  44.             @Override  
  45.             public void onStart() {  
  46.                 clearOutputs();  
  47.             }  
  48.   
  49.             @Override  
  50.             public void onSuccess(int statusCode, Header[] headers,  
  51.                     byte[] response) {  
  52.                 debugHeaders(LOG_TAG, headers);  
  53.                 debugStatusCode(LOG_TAG, statusCode);  
  54.                 debugResponse(LOG_TAG, new String(response));  
  55.             }  
  56.   
  57.             @Override  
  58.             public void onFailure(int statusCode, Header[] headers,  
  59.                     byte[] errorResponse, Throwable e) {  
  60.                 debugHeaders(LOG_TAG, headers);  
  61.                 debugStatusCode(LOG_TAG, statusCode);  
  62.                 debugThrowable(LOG_TAG, e);  
  63.                 if (errorResponse != null) {  
  64.                     debugResponse(LOG_TAG, new String(errorResponse));  
  65.                 }  
  66.             }  
  67.         };  
  68.     }  
  69. }
复制代码
还是比较简短的。他继承了SampleParentActivity。在SampleParentActivity里已经为主界面设置了主要布局和监听。所以这使得getsample代码很简短。以下是SampleParentActivity中的主要代码和调用步骤。
  1. public void onRunButtonPressed() {  
  2.     addRequestHandle(executeSample(getAsyncHttpClient(),  
  3.             (urlEditText == null || urlEditText.getText() == null) ? getDefaultURL() : urlEditText.getText().toString(),  
  4.             getRequestHeaders(),  
  5.             getRequestEntity(),  
  6.             getResponseHandler()));  
  7. }
复制代码
在SampleParentActivity里已经为run这个button添加了监听,点击后执行上面这个方法。其中addRequestHandle()使子类可以通过重载executeSample()方法而实现不同的功能 。
  1. @Override  
  2.    public void addRequestHandle(RequestHandle handle) {  
  3.        if (null != handle) {  
  4.            requestHandles.add(handle);  
  5.        }  
  6.    }
复制代码
然后是getAsyncHttpClient()方法,得到异步的http链接。是这个开源项目中的核心部分了。在SampleParentActivity类里一开头就声明好了这一个属性。

再看getsample里实现的这个executeSample方法


  1. @Override  
  2.     public RequestHandle executeSample(AsyncHttpClient client, String URL, Header[] headers, HttpEntity entity, ResponseHandlerInterface responseHandler) {  
  3.         return client.get(this, URL, headers, null, responseHandler);  
  4.     }
复制代码

主要就是调用AsyncHttpClient类内封装的方法完成操作。
下面主要分析一下AsyncHttpClient类。这个类有1159行代码。所以复制上来不太便于分析,这里根据get的调用及执行步骤进行分析 。

当getSamlpe执行AsyncHttpClient的get方法时。调用如下代码。
  1. /**
  2.     * Perform a HTTP GET request and track the Android Context which initiated the request with
  3.     * customized headers
  4.     *
  5.     * @param context         Context to execute request against
  6.     * @param url             the URL to send the request to.
  7.     * @param headers         set headers only for this request
  8.     * @param params          additional GET parameters to send with the request.
  9.     * @param responseHandler the response handler instance that should handle the response.
  10.     * @return RequestHandle of future request process
  11.     */  
  12.    public RequestHandle get(Context context, String url, Header[] headers, RequestParams params, ResponseHandlerInterface responseHandler) {  
  13.        HttpUriRequest request = new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params));  
  14.        if (headers != null) request.setHeaders(headers);  
  15.        return sendRequest(httpClient, httpContext, request, null, responseHandler,  
  16.                context);  
  17.    }  
复制代码
Context:参数是上下文,这里说一下,android系统中的activity中继承于Context的,所以我们经常在Context参数中传入XXXactivity.this:实际上就是传入本activity的超类。

url :就不用说了,是请求的地址。在这里是"https://httpbin.org/get";

headers

HTTP是“Hypertext Transfer Protocol”的所写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的,比如这篇文章。

HTTP Headers是HTTP请求和相应的核心,它承载了关于客户端浏览器,请求页面,服务器等相关的信息。


示例当你在浏览器地址栏里键入一个url,你的浏览器将会类似如下的http请求:
  1. GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
  2. Host: net.tutsplus.com
  3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  5. Accept-Language: en-us,en;q=0.5
  6. Accept-Encoding: gzip,deflate
  7. Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
  8. Keep-Alive: 300
  9. Connection: keep-alive
  10. Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120
  11. Pragma: no-cache
  12. Cache-Control: no-cache
复制代码
HttpEntity 翻译过来是http实体,我的理解是http请求的主要内容,如我们如果是post操作那么这个实体内应该是需要post的内容,如果是get操作,那这个实就是服务器内返回过来的数据。所以在getSample里传入为null

ResponseHandlerInterface 这个是项目中自定义的一个handler用于编写在请求开始 成功 失败,三种情况后需要执行的操作。

继续看。在 AsyncHttpClient的get方法中httpget的构造参数执行了getUrlWithQueryString()方法,这个方法将返回一个String 类型的uri.主要是将参数进行整合最后返回一个带请求参数的uri。下面这个方法的代码

  1. <span style="line-height: 1.5;">  </span><span style="line-height: 1.5;">/**</span>
复制代码
第一个参数 是否转化字符编码把空格替换成%20, 有时候在网址中经常发现原来的空格会被变成%20就是这个道理。
然后参数会被以?参数名=值添加在url后面。RequestParams类型本是一个map表,这里执行了一个getParamString方法将map表转化成字符串并去了空格,根据深度优先的思路进行分析。
  1.   <span style="line-height: 1.5;">protected String getParamString() {</span><span style="line-height: 1.5;"> </span><span style="line-height: 1.5;"> </span>
复制代码
第二个参数 是默认编码类型 初值为ut8
  1. protected String contentEncoding = HTTP.UTF_8;
复制代码
那么再看getParamsList();
  1. protected List<BasicNameValuePair> getParamsList() {  
  2.        List<BasicNameValuePair> lparams = new LinkedList();  
  3.   
  4.        for (ConcurrentHashMap.Entry<String, String> entry : urlParams.entrySet()) {  
  5.            lparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));  
  6.        }  
  7.   
  8.        lparams.addAll(getParamsList(null, urlParamsWithObjects));  
  9.   
  10.        return lparams;  
  11.    }  
复制代码
返回值 是一个链表,类型是基本键值对。是http.message的一个类型。当将所有参数以键值对的方式放在链表里之后又执行了一个addall方法 。由于 这个不常用 所以还是看了一个代码
  1. /**
  2.   * Adds the objects in the specified Collection to this {@code LinkedList}.
  3.   *
  4.   * @param collection
  5.   *            the collection of objects.
  6.   * @return {@code true} if this {@code LinkedList} is modified,
  7.   *         {@code false} otherwise.
  8.   */  
  9. @Override  
  10. public boolean addAll(Collection<? extends E> collection) {  
  11.      int adding = collection.size();  
  12.      if (adding == 0) {  
  13.          return false;  
  14.      }  
  15.      Collection<? extends E> elements = (collection == this) ?  
  16.              new ArrayList<E>(collection) : collection;  
  17.   
  18.      Link<E> previous = voidLink.previous;  
  19.      for (E e : elements) {  
  20.          Link<E> newLink = new Link<E>(e, previous, null);  
  21.          previous.next = newLink;  
  22.          previous = newLink;  
  23.      }  
  24.      previous.next = voidLink;  
  25.      voidLink.previous = previous;  
  26.      size += adding;  
  27.      modCount++;  
  28.      return true;  
  29. }
复制代码

看完就明白了,是将一个集合加在了整个链表上。
那么再看getParamsList方法 中的getParamsList(String key, Object value)方法
  1. private List<BasicNameValuePair> getParamsList(String key, Object value) {  
  2.        List<BasicNameValuePair> params = new LinkedList();  
  3.        if (value instanceof Map) {  
  4.            Map map = (Map) value;  
  5.            List list = new ArrayList<Object>(map.keySet());  
  6.            // Ensure consistent ordering in query string  
  7.            Collections.sort(list);  
  8.            for (Object nestedKey : list) {  
  9.                if (nestedKey instanceof String) {  
  10.                    Object nestedValue = map.get(nestedKey);  
  11.                    if (nestedValue != null) {  
  12.                        params.addAll(getParamsList(key == null ? (String) nestedKey : String.format("%s[%s]", key, nestedKey),  
  13.                                nestedValue));  
  14.                    }  
  15.                }  
  16.            }  
  17.        } else if (value instanceof List) {  
  18.            List list = (List) value;  
  19.            for (Object nestedValue : list) {  
  20.                params.addAll(getParamsList(String.format("%s[]", key), nestedValue));  
  21.            }  
  22.        } else if (value instanceof Object[]) {  
  23.            Object[] array = (Object[]) value;  
  24.            for (Object nestedValue : array) {  
  25.                params.addAll(getParamsList(String.format("%s[]", key), nestedValue));  
  26.            }  
  27.        } else if (value instanceof Set) {  
  28.            Set set = (Set) value;  
  29.            for (Object nestedValue : set) {  
  30.                params.addAll(getParamsList(key, nestedValue));  
  31.            }  
  32.        } else if (value instanceof String) {  
  33.            params.add(new BasicNameValuePair(key, (String) value));  
  34.        }  
  35.        return params;  
  36.    }  
复制代码


这里看到其实 是根据value参数的类型提供了不同的构造  List<BasicNameValuePair> 返回值的方法
那么在getParamsList(String key, Object value)的参数urlParamsWithObjects 就是传说中httpentity的数据承载了吧。
  1. protected final ConcurrentHashMap<String, String> urlParams = new ConcurrentHashMap();  
  2. protected final ConcurrentHashMap<String, StreamWrapper> streamParams = new ConcurrentHashMap();  
  3. protected final ConcurrentHashMap<String, FileWrapper> fileParams = new ConcurrentHashMap();  
  4. protected final ConcurrentHashMap<String, Object> urlParamsWithObjects = new ConcurrentHashMap();  
复制代码

我们看到这个RequestParams类内有四种这样的hashmap用于放数据的变量 。所以它应该是根据不同的参数类型选择不同的数据载体.
之前的return URLEncodedUtils.format(getParamsList(), contentEncoding);
是对整个字符串进行编码转换工作,转换成了utf8
那么分析完毕。回到AsyncHttpClient类的get方法
  1. <font size="2">public RequestHandle get(Context context, String url, Header[] headers, RequestParams params, ResponseHandlerInterface responseHandler) {  
  2.     HttpUriRequest request = new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params));  
  3.     if (headers != null) request.setHeaders(headers);  
  4.     return sendRequest(httpClient, httpContext, request, null, responseHandler,  
  5.             context);  
  6. }  </font>
复制代码
设置了headers之后执行发送请求
  1. protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) {  
  2.      if (uriRequest == null) {  
  3.          throw new IllegalArgumentException("HttpUriRequest must not be null");  
  4.      }  
  5.   
  6.      if (responseHandler == null) {  
  7.          throw new IllegalArgumentException("ResponseHandler must not be null");  
  8.      }  
  9.   
  10.      if (responseHandler.getUseSynchronousMode()) {  
  11.          throw new IllegalArgumentException("Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead.");  
  12.      }  
  13.   
  14.      if (contentType != null) {  
  15.          uriRequest.setHeader("Content-Type", contentType);  
  16.      }  
  17.   
  18.      responseHandler.setRequestHeaders(uriRequest.getAllHeaders());  
  19.      responseHandler.setRequestURI(uriRequest.getURI());  
  20.   
  21.      AsyncHttpRequest request = new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler);  
  22.      threadPool.submit(request);  
  23.      RequestHandle requestHandle = new RequestHandle(request);  
  24.   
  25.      if (context != null) {  
  26.          // Add request to request map  
  27.          List<RequestHandle> requestList = requestMap.get(context);  
  28.          if (requestList == null) {  
  29.              requestList = new LinkedList();  
  30.              requestMap.put(context, requestList);  
  31.          }  
  32.   
  33.          if (responseHandler instanceof RangeFileAsyncHttpResponseHandler)  
  34.              ((RangeFileAsyncHttpResponseHandler) responseHandler).updateRequestHeaders(uriRequest);  
  35.   
  36.          requestList.add(requestHandle);  
  37.   
  38.          Iterator<RequestHandle> iterator = requestList.iterator();  
  39.          while (iterator.hasNext()) {  
  40.              if (iterator.next().shouldBeGarbageCollected()) {  
  41.                  iterator.remove();  
  42.              }  
  43.          }  
  44.      }  
  45.   
  46.      return requestHandle;  
  47. }  
复制代码
又是好长一段前面包括的是各种错误处理、
在这个方法 中看到了
  1. public class AsyncHttpRequest implements Runnable   
复制代码
这个类实现 了runnable接口,这就是为什么这个开源项目可以执行异步请求并且可以控制取消了
  1. <font size="2">@Override  
  2.   public void run() {  
  3.       if (isCancelled()) {  
  4.           return;  
  5.       }  
  6.   
  7.       if (responseHandler != null) {  
  8.           responseHandler.sendStartMessage();  
  9.       }  
  10.   
  11.       if (isCancelled()) {  
  12.           return;  
  13.       }  
  14.   
  15.       try {  
  16.           makeRequestWithRetries();  
  17.       } catch (IOException e) {  
  18.           if (!isCancelled() && responseHandler != null) {  
  19.               responseHandler.sendFailureMessage(0, null, null, e);  
  20.           } else {  
  21.               Log.e("AsyncHttpRequest", "makeRequestWithRetries returned error, but handler is null", e);  
  22.           }  
  23.       }  
  24.   
  25.       if (isCancelled()) {  
  26.           return;  
  27.       }  
  28.   
  29.       if (responseHandler != null) {  
  30.           responseHandler.sendFinishMessage();  
  31.       }  </font>
  32.   <font size="2">
  33.       isFinished = true;  
  34.   }  </font>
复制代码
在run方法 内我们看到。如果responseHandler不为null那么就向它发送开始消息 ,我们之前看到过这个项目可以对开始 成功 失败三个状态执行不同的自定义操作就是通过它来实现的。之后 开始发送请求

在请求开始之前和开始之后 各有一个取消的检查,这就是说如果在请求之前取消请求将不会被执行,为了减少操作。在请求之后取消将不会发送finish消息 ,避免执行我们自定义 的finish方法


在用AsyncHttpRequest声明好runnable对象之后 提交到线程池里


  1. <font color="#362e2b"><font face="Arial"><font size="2">threadPool.submit(request);  </font></font></font>
复制代码
这个线程池应该在AsyncHttpClient的构造函数里进行了初值的设置

  1. <font color="#362e2b"><font face="Arial"><font size="2">/**
  2.   * Creates a new AsyncHttpClient with default constructor arguments values
  3.   */  
  4. public AsyncHttpClient() {  
  5.      this(false, 80, 443);  
  6. }  </font></font></font>
复制代码

这是他的无参构造函数,也就是我们最常用的那个。、
将调 用第二个构造 函数

  1. <font color="#362e2b"><font face="Arial"><font size="2">public AsyncHttpClient(boolean fixNoHttpResponseException, int httpPort, int httpsPort) {  
  2.     this(getDefaultSchemeRegistry(fixNoHttpResponseException, httpPort, httpsPort));  
  3. }  </font></font></font>
复制代码
getDefaultSchemeRegistry方法用于获得默认的协议模式。比如“http”或“https”同时包含一些协议属性,比如默认端口,用来为给定协议创建java.net.Socket实例的套接字工厂。SchemeRegistry类用来维持一组Scheme,当去通过请求URI建立连接时,HttpClient可以从中选择:

  1. <font color="#362e2b"><font face="Arial"><font size="2">private static SchemeRegistry getDefaultSchemeRegistry(boolean fixNoHttpResponseException, int httpPort, int httpsPort) {  
  2.       if (fixNoHttpResponseException) {  
  3.           Log.d(LOG_TAG, "Beware! Using the fix is insecure, as it doesn't verify SSL certificates.");  
  4.       }  
  5.   
  6.       if (httpPort < 1) {  
  7.           httpPort = 80;  
  8.           Log.d(LOG_TAG, "Invalid HTTP port number specified, defaulting to 80");  
  9.       }  
  10.   
  11.       if (httpsPort < 1) {  
  12.           httpsPort = 443;  
  13.           Log.d(LOG_TAG, "Invalid HTTPS port number specified, defaulting to 443");  
  14.       }  
  15.   
  16.       // Fix to SSL flaw in API < ICS  
  17.       // See https://code.google.com/p/android/issues/detail?id=13117  
  18.       SSLSocketFactory sslSocketFactory;  
  19.       if (fixNoHttpResponseException)  
  20.           sslSocketFactory = MySSLSocketFactory.getFixedSocketFactory();  
  21.       else  
  22.           sslSocketFactory = SSLSocketFactory.getSocketFactory();  
  23.   
  24.       SchemeRegistry schemeRegistry = new SchemeRegistry();  
  25.       schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), httpPort));  
  26.       schemeRegistry.register(new Scheme("https", sslSocketFactory, httpsPort));  
  27.   
  28.       return schemeRegistry;  
  29.   }  </font></font></font>
复制代码
第一个布尔型参数设置了是否验证其ssl证书。ssl是一种加密协议,

第二个参数 是http协议的端口

第三个参数 是https使用的端口

然后又将调用Asynchttpclient的第三个构造参数


  1. <font color="#362e2b"><font face="Arial"><font size="2">public AsyncHttpClient(SchemeRegistry schemeRegistry) {  
  2.   
  3.        BasicHttpParams httpParams = new BasicHttpParams();  
  4.   
  5.        ConnManagerParams.setTimeout(httpParams, timeout);  
  6.        ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections));  
  7.        ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);  
  8.   
  9.        HttpConnectionParams.setSoTimeout(httpParams, timeout);  
  10.        HttpConnectionParams.setConnectionTimeout(httpParams, timeout);  
  11.        HttpConnectionParams.setTcpNoDelay(httpParams, true);  
  12.        HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);  
  13.   
  14.        HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);  
  15.        HttpProtocolParams.setUserAgent(httpParams, String.format("android-async-http/%s (http://loopj.com/android-async-http)", VERSION));  
  16.   
  17.        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry);  
  18.   
  19.        threadPool = Executors.newCachedThreadPool();  
  20.        requestMap = new WeakHashMap();  
  21.        clientHeaderMap = new HashMap();  
  22.   
  23.        httpContext = new SyncBasicHttpContext(new BasicHttpContext());  
  24.        httpClient = new DefaultHttpClient(cm, httpParams);  
  25.        httpClient.addRequestInterceptor(new HttpRequestInterceptor() {  
  26.            @Override  
  27.            public void process(HttpRequest request, HttpContext context) {  
  28.                if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {  
  29.                    request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);  
  30.                }  
  31.                for (String header : clientHeaderMap.keySet()) {  
  32.                    if (request.containsHeader(header)) {  
  33.                        Header overwritten = request.getFirstHeader(header);  
  34.                        Log.d(LOG_TAG,  
  35.                                String.format("Headers were overwritten! (%s | %s) overwrites (%s | %s)",  
  36.                                        header, clientHeaderMap.get(header),  
  37.                                        overwritten.getName(), overwritten.getValue())  
  38.                        );  
  39.                    }  
  40.                    request.addHeader(header, clientHeaderMap.get(header));  
  41.                }  
  42.            }  
  43.        });  
  44.   
  45.        httpClient.addResponseInterceptor(new HttpResponseInterceptor() {  
  46.            @Override  
  47.            public void process(HttpResponse response, HttpContext context) {  
  48.                final HttpEntity entity = response.getEntity();  
  49.                if (entity == null) {  
  50.                    return;  
  51.                }  
  52.                final Header encoding = entity.getContentEncoding();  
  53.                if (encoding != null) {  
  54.                    for (HeaderElement element : encoding.getElements()) {  
  55.                        if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {  
  56.                            response.setEntity(new InflatingEntity(entity));  
  57.                            break;  
  58.                        }  
  59.                    }  
  60.                }  
  61.            }  
  62.        });  
  63.   
  64.        httpClient.addRequestInterceptor(new HttpRequestInterceptor() {  
  65.            @Override  
  66.            public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {  
  67.                AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);  
  68.                CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(  
  69.                        ClientContext.CREDS_PROVIDER);  
  70.                HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);  
  71.   
  72.                if (authState.getAuthScheme() == null) {  
  73.                    AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());  
  74.                    Credentials creds = credsProvider.getCredentials(authScope);  
  75.                    if (creds != null) {  
  76.                        authState.setAuthScheme(new BasicScheme());  
  77.                        authState.setCredentials(creds);  
  78.                    }  
  79.                }  
  80.            }  
  81.        }, 0);  
  82.   
  83.        httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_MAX_RETRIES, DEFAULT_RETRY_SLEEP_TIME_MILLIS));  
  84.    }  </font></font></font>
复制代码
在设置了一些基本项之后 我们看到了线程池

  1. <font color="#362e2b"><font face="Arial">threadPool = Executors.newCachedThreadPool();  </font></font>
复制代码
这个线程池我在之前介绍过 这里再说一遍


创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,

那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

至此get方法的执行过程就到这儿。好复杂的已经,有的函数没有分析到是因为是封装在jar包内。




其他资源分享:

【强荐!】2016年最新Android学习路线图——按此路线图学习月薪过万{ 火速收入}

Android中Bitmap,byte[],Drawable相互转化详解(超实用)

【源码分享】Android启动相机拍照并返回图片

Andriod案例源码分享--Android_系统UI布局以及设计规则

Android机器人带你玩转实现游戏2048



作者: baby14    时间: 2019-6-26 08:06
多谢分享




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2