AsyncHttpClient 源碼分析,asynchttpclient源碼
開源的AsyncHttp是基於Apache HTTP Client封裝的一個庫,比較簡單,回調進行擷取資料,不用自己處理線程和執行個體化Handler
上一篇寫了個 AsyncHttpClient 擷取圖片和網頁資料示範 簡單用法
AsyncHttpClient.java 是暴露的介面,最主要的就是Post和Get 2種,還有其他的HTTP請求方式 比如還有Delete,Patch操作,不是很常用
線程池用的是 Executors.newCachedThreadPool() 這個源碼裡面顯示 核心線程是0,建立的線程60秒後不用就銷毀,感覺比較符合網路頻繁操作一段時間,
比如ListView非同步下載Bitmap圖片
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
RequestHandle 返回的請求運行對象,可以cancel一個請求 ,但不一定能成功。
建立非同步請求用於任務執行
protected AsyncHttpRequest newAsyncHttpRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) { return new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler);}//發送請求 protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) { //判斷代碼省去。。。。。只看關鍵的 if (contentType != null) { if (uriRequest instanceof HttpEntityEnclosingRequestBase && ((HttpEntityEnclosingRequestBase) uriRequest).getEntity() != null) { Log.w(LOG_TAG, "Passed contentType will be ignored because HttpEntity sets content type"); } else { uriRequest.setHeader(HEADER_CONTENT_TYPE, contentType); } } responseHandler.setRequestHeaders(uriRequest.getAllHeaders()); responseHandler.setRequestURI(uriRequest.getURI()); //構造一個請求對象,線程運行 AsyncHttpRequest request = newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context); threadPool.submit(request);//提交任務 RequestHandle requestHandle = new RequestHandle(request); //這個地方用來判斷之前是否有請求,回收不必要的請求對象,因為RequestHandle可以取消任務,用的是Weak對象 if (context != null) { // Add request to request map List<RequestHandle> requestList = requestMap.get(context); synchronized (requestMap) { if (requestList == null) { requestList = Collections.synchronizedList(new LinkedList<RequestHandle>()); requestMap.put(context, requestList); } } requestList.add(requestHandle); Iterator<RequestHandle> iterator = requestList.iterator(); while (iterator.hasNext()) { if (iterator.next().shouldBeGarbageCollected()) { //清理不用的Weak對象 iterator.remove(); } } } return requestHandle; }
構造請求返回對象,可以取消請求
RequestHandle requestHandle = new RequestHandle(request);
ResponseHandlerInterface 回調介面定義了 任務的開始,過程,結束還有錯誤訊息
UI訊息在哪裡發送? 在抽象類別AsyncHttpResponseHandler建構函式裡面
//UI線程裡面的Handler執行個體化是在建構函式裡面,預設就是myLooper,預設建構函式是傳null的 public AsyncHttpResponseHandler(Looper looper) { this.looper = looper == null ? Looper.myLooper() : looper; // Use asynchronous mode by default.預設非同步 setUseSynchronousMode(false); // Do not use the pool's thread to fire callbacks by default. setUsePoolThread(false); } @Override public void setUseSynchronousMode(boolean sync) { // A looper must be prepared before setting asynchronous mode. if (!sync && looper == null) { sync = true; Log.w(LOG_TAG, "Current thread has not called Looper.prepare(). Forcing synchronous mode."); } // If using asynchronous mode. if (!sync && handler == null) { // Create a handler on current thread to submit tasks handler = new ResponderHandler(this, looper);//初始化,看ResponderHandler } else if (sync && handler != null) { // TODO: Consider adding a flag to remove all queued messages. handler = null; } useSynchronousMode = sync; } private static class ResponderHandler extends Handler { private final AsyncHttpResponseHandler mResponder; ResponderHandler(AsyncHttpResponseHandler mResponder, Looper looper) { super(looper); this.mResponder = mResponder; } @Override public void handleMessage(Message msg) { mResponder.handleMessage(msg); //最終提交訊息處理的地方 } }
AsyncHttpResponseHandler 的子類有多個,包括Binary,Text,JSON 回調
UML 簡單的類圖