没开looper
的子线程中使用AsyncHttpClient
会出现下面的异常:
Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead.
通过翻阅源码,发现AsyncHttpClient
的请求最终会被提交到线程池中运行,那么就奇怪了,为什么不能在没开looper的子线程中运行呢?
上源码:
请求最终会调用AsyncHttpClient
的sendRequest
方法
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");
} else if (responseHandler == null) {
throw new IllegalArgumentException("ResponseHandler must not be null");
} else 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.");
} else {
if (contentType != null) {
if (uriRequest instanceof HttpEntityEnclosingRequestBase && ((HttpEntityEnclosingRequestBase)uriRequest).getEntity() != null && uriRequest.containsHeader("Content-Type")) {
log.w("AsyncHttpClient", "Passed contentType will be ignored because HttpEntity sets content type");
} else {
uriRequest.setHeader("Content-Type", contentType);
}
}
responseHandler.setRequestHeaders(uriRequest.getAllHeaders());
responseHandler.setRequestURI(uriRequest.getURI());
AsyncHttpRequest request = this.newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context);
this.threadPool.submit(request);
RequestHandle requestHandle = new RequestHandle(request);
if (context != null) {
Map var10 = this.requestMap;
List requestList;
synchronized(this.requestMap) {
requestList = (List)this.requestMap.get(context);
if (requestList == null) {
requestList = Collections.synchronizedList(new LinkedList());
this.requestMap.put(context, requestList);
}
}
requestList.add(requestHandle);
Iterator iterator = requestList.iterator();
while(iterator.hasNext()) {
if (((RequestHandle)iterator.next()).shouldBeGarbageCollected()) {
iterator.remove();
}
}
}
return requestHandle;
}
}
在方法中可以看到这么一句话
AsyncHttpRequest request = this.newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context);
this.threadPool.submit(request);
所以可以断定会被提交到线程池中,而报错的原因是下面这句话:
else 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.");
responseHandler
是一个接口,具体实现类是AsyncHttpResponseHandler
,这是一个基类,下面有很多子类
而在AsyncHttpResponseHandler
类中有一个setUseSynchronousMode
方法了一个setUsePoolThread
方法
public void setUseSynchronousMode(boolean sync) {
if (!sync && this.looper == null) {
sync = true;
AsyncHttpClient.log.w("AsyncHttpRH", "Current thread has not called Looper.prepare(). Forcing synchronous mode.");
}
if (!sync && this.handler == null) {
this.handler = new AsyncHttpResponseHandler.ResponderHandler(this, this.looper);
} else if (sync && this.handler != null) {
this.handler = null;
}
this.useSynchronousMode = sync;
}
public void setUsePoolThread(boolean pool) {
if (pool) {
this.looper = null;
this.handler = null;
}
this.usePoolThread = pool;
}
而在AsyncHttpResponseHandler
类中的构造方法中,这两个属性全部被设置为false,在setUseSynchronousMode
法中
if (!sync && this.looper == null) {
sync = true;
AsyncHttpClient.log.w("AsyncHttpRH", "Current thread has not called Looper.prepare(). Forcing synchronous mode.");
}
/*something*/
this.useSynchronousMode = sync;
因为子线程没有looper
,所以useSynchronousMode
会被设置为true,
所以会报上面的异常,而在主线程中,因为主线程默认开启了looper
所以不会报异常,至于looper
干嘛用的,个人猜测,内部使用looper
配合handler
做了某些同步操作。