android-async-http 源碼流程淺析

一、get()\put()\post()\delete()\head()\patch() 的執行流程分析

Step1    
個接口首先分裝對應的HttpGet、HttpPut、HttpPost等,然後再封裝成HttpUriRequest;
調用sendRequest(...):
/**
* 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 (uriRequest == null) {
throw new IllegalArgumentException("HttpUriRequest must not be null");
}

if (responseHandler == null) {
throw new IllegalArgumentException("ResponseHandler must not be null");
}

if (responseHandler.getUseSynchronousMode() && !responseHandler.getUsePoolThread()) {
throw new IllegalArgumentException("Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead.");
}

if (contentType != null) {
if (uriRequest instanceof HttpEntityEnclosingRequestBase && ((HttpEntityEnclosingRequestBase) uriRequest).getEntity() != null && uriRequest.containsHeader(HEADER_CONTENT_TYPE)) {
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);

if (context != null) {
List<RequestHandle> requestList
;
// Add request to request map
synchronized (requestMap) {
requestList = requestMap.get(context)
;
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()) {
iterator.remove()
;
}
}
}

return requestHandle;
}
將HttpUriRequest中的head和Uri信息設置到responseHandler中,同時根據入參構建AsyncHttpRequest對象(實際是一個Runnable),然後將這個Request對象提交到線程池中:
將Request對象封裝到RequsetHandle中,Client中保存有RequestHandle的緩存列表,Map<Context, List<RequestHandle>> requestMap,request提交到線程中後,會將request保存到requestList中,同時將context和requestList作爲key-value保存到requestMap中。
HTTP請求最終的執行時在AsyncHttpRequest的run中執行的。
Step2 AsyncHttpRequest  run()
@Override
public void run() {
if (isCancelled()) {
return;
}

// Carry out pre-processing for this request only once.
if (!isRequestPreProcessed) {
isRequestPreProcessed = true;
onPreProcessRequest(this);
}

if (isCancelled()) {
return;
}

responseHandler.sendStartMessage();

if (isCancelled()) {
return;
}

try {
makeRequestWithRetries();
} catch (IOException e) {
if (!isCancelled()) {
responseHandler.sendFailureMessage(
0, null, null, e);
} else {
AsyncHttpClient.log.e(
"AsyncHttpRequest", "makeRequestWithRetries returned error", e);
}
}

if (isCancelled()) {
return;
}

responseHandler.sendFinishMessage()
;

if (isCancelled()) {
return;
}

// Carry out post-processing for this request.
onPostProcessRequest(this);

isFinished = true;
}
 isCancle是最爲請求中斷的標誌,如果在請求執行過程中,外部執行了cancel請求的話,request檢測到isCancelled()就直接return了,不會再執行後面的過程。
同時請求各階段都可以通過ResponseHandler重載sendxxxMessage接口,向外部回調通知執行階段;
請求執行是在makeRequestWithRetries()中,
Step3 makeRequestWithRetries(),  
private void makeRequestWithRetries() throws IOException {
boolean retry = true;
IOException cause = null;
HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();
try {
while (retry) {
try {
makeRequest();
return;
} catch (UnknownHostException e) {
cause = new IOException("UnknownHostException exception: " + e.getMessage(), e);
retry = (executionCount > 0) && retryHandler.retryRequest(e, ++executionCount, context);
} catch (NullPointerException e) {
cause = new IOException("NPE in HttpClient: " + e.getMessage());
retry = retryHandler.retryRequest(cause, ++executionCount, context);
} catch (IOException e) {
if (isCancelled()) {
return;
}
cause = e
;
retry = retryHandler.retryRequest(cause, ++executionCount, context);
}
if (retry) {
responseHandler.sendRetryMessage(executionCount)
;
}
}
}
catch (Exception e) {
// catch anything else to ensure failure message is propagated
AsyncHttpClient.log.e("AsyncHttpRequest", "Unhandled exception origin cause", e);
cause = new IOException("Unhandled exception: " + e.getMessage(), cause);
}
通過boolean retry來控制請求失敗後重試,
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");
}

if (responseHandler instanceof RangeFileAsyncHttpResponseHandler) {
((RangeFileAsyncHttpResponseHandler) responseHandler).updateRequestHeaders(request);
}
//此處的client爲AbstractHttpClient
HttpResponse response = client.execute(request, context);

if (isCancelled()) {
return;
}

// Carry out pre-processing for this response.
responseHandler.onPreProcessResponse(responseHandler, response);

if (isCancelled()) {
return;
}

// The response is ready, handle it.
responseHandler.sendResponseMessage(response);

if (isCancelled()) {
return;
}

// Carry out post-processing for this response.
responseHandler.onPostProcessResponse(responseHandler, response);
}
這個過程比較簡單,調用Android原始的HttpClient來執行HttpUriRequest,請求的結果通過responeseHandler發送出去;
Step4 結果回調sendResponseMessage()
sendResponseMessage的具體實現在AsyncHttpResponseHandler中,
@Override
public void sendResponseMessage(HttpResponse response) throws IOException {
// do not process if request has been cancelled
if (!Thread.currentThread().isInterrupted()) {
StatusLine status = response.getStatusLine();
byte[] responseBody;
responseBody = getResponseData(response.getEntity());
// additional cancellation check as getResponseData() can take non-zero time to process
if (!Thread.currentThread().isInterrupted()) {
if (status.getStatusCode() >= 300) {
sendFailureMessage(status.getStatusCode(), response.getAllHeaders(), responseBody, new HttpResponseException(status.getStatusCode(), status.getReasonPhrase()));
} else {
sendSuccessMessage(status.getStatusCode(), response.getAllHeaders(), responseBody);
}
}
}
}
解析HttpResponse中數據,根據statusCode來決定是回調成功還是失敗,
@Override
final public void sendSuccessMessage(int statusCode, Header[] headers, byte[] responseBytes) {
sendMessage(obtainMessage(SUCCESS_MESSAGE, new Object[]{statusCode, headers, responseBytes}));
}

@Override
final public void sendFailureMessage(int statusCode, Header[] headers, byte[] responseBody, Throwable throwable) {
sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[]{statusCode, headers, responseBody, throwable}));
}
最終都是通過sendMessage來處理,
protected void sendMessage(Message msg) {
if (getUseSynchronousMode() || handler == null) {
handleMessage(msg);
} else if (!Thread.currentThread().isInterrupted()) { // do not send messages if request has been cancelled
Utils.asserts(handler != null, "handler should not be null!");
handler.sendMessage(msg);
}
}
sendMessage中,會根據之前設置的同步還是異步模式來分開處理,同步模式直接調用handleMessage(),異步模式下,將封裝了結果的message通過handler傳遞到ui線程處理,最終也是調用到handlerMessage();
protected void handleMessage(Message message) {
Object[] response;

try {
switch (message.what) {
case SUCCESS_MESSAGE:
response = (Object[]) message.obj;
if (response != null && response.length >= 3) {
onSuccess((Integer) response[0], (Header[]) response[1], (byte[]) response[2]);
} else {
AsyncHttpClient.log.e(LOG_TAG, "SUCCESS_MESSAGE didn't got enough params");
}
break;
case FAILURE_MESSAGE:
response = (Object[]) message.obj;
if (response != null && response.length >= 4) {
onFailure((Integer) response[0], (Header[]) response[1], (byte[]) response[2], (Throwable) response[3]);
} else {
AsyncHttpClient.log.e(LOG_TAG, "FAILURE_MESSAGE didn't got enough params");
}
break;
case START_MESSAGE:
onStart();
break;
case FINISH_MESSAGE:
onFinish();
break;
case PROGRESS_MESSAGE:
response = (Object[]) message.obj;
if (response != null && response.length >= 2) {
try {
onProgress((Long) response[0], (Long) response[1]);
} catch (Throwable t) {
AsyncHttpClient.log.e(LOG_TAG, "custom onProgress contains an error", t);
}
} else {
AsyncHttpClient.log.e(LOG_TAG, "PROGRESS_MESSAGE didn't got enough params");
}
break;
case RETRY_MESSAGE:
response = (Object[]) message.obj;
if (response != null && response.length == 1) {
onRetry((Integer) response[0]);
} else {
AsyncHttpClient.log.e(LOG_TAG, "RETRY_MESSAGE didn't get enough params");
}
break;
case CANCEL_MESSAGE:
onCancel();
break;
}
} catch (Throwable error) {
onUserException(error);
}
}
到這裏,就可以將http請求的結果通過onSuccess()\onFail()\onCancel(),拋回給外部調用者;
二、Http請求取消的執行流程
入口:AsyncHttpClient.cancleRequests(context,boolean)
public void cancelRequests(final Context context, final boolean mayInterruptIfRunning) {
if (context == null) {
log.e(LOG_TAG, "Passed null Context to cancelRequests");
return;
}

final List<RequestHandle> requestList = requestMap.get(context);
requestMap.remove(context);

if (Looper.myLooper() == Looper.getMainLooper()) {
Runnable runnable = new Runnable() {
@Override
public void run() {
cancelRequests(requestList, mayInterruptIfRunning);
}
};
threadPool.submit(runnable);
} else {
cancelRequests(requestList, mayInterruptIfRunning);
}
}
通過Context從requestMap中找到該context下所有的請求集合,得到requestList,然後調用cancleRequests的同名重載函數,
private void cancelRequests(final List<RequestHandle> requestList, final boolean mayInterruptIfRunning) {
if (requestList != null) {
for (RequestHandle requestHandle : requestList) {
requestHandle.cancel(mayInterruptIfRunning);
}
}
}
遍歷requestList,對每個requestHandle調用cancle(boolean );
public boolean cancel(final boolean mayInterruptIfRunning) {
final AsyncHttpRequest _request = request.get();
if (_request != null) {
if (Looper.myLooper() == Looper.getMainLooper()) {
new Thread(new Runnable() {
@Override
public void run() {
_request.cancel(mayInterruptIfRunning);
}
}).start();
// Cannot reliably tell if the request got immediately canceled at this point
// we'll assume it got cancelled
return true;
} else {
return _request.cancel(mayInterruptIfRunning);
}
}
return false;
}
從RequestHandle中取出之前保存的AsyncHttpRequest對象,並執行cancel();
public boolean cancel(boolean mayInterruptIfRunning) {
isCancelled.set(true);
request.abort();
return isCancelled();
}
回到AsyncHttpRequest中的cancle,isCancelled是一個AtomicBoolean對象,此處將狀態設置爲true後,返回isCancelled();
public boolean isCancelled() {
boolean cancelled = isCancelled.get();
if (cancelled) {
sendCancelNotification();
}
return cancelled;
}
返回的值實際就是剛纔設置的true;同時發送sendCancleNotification(),消息發送過程參考 Step4,
isCancelled()爲true以後,http請求執行過程就可以退出了,參考Step3;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章