Retrofit发起请求过程分析
在使用Retrofit时,发起网络请求的典型代码如下:
代码示例
// Call<User> call = apiService.getUser("exampleUser");
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
// Handle response
}
@Override
public void onFailure(Call<User> call, Throwable t) {
// Handle failure
}
});
源码分析
在分析Call对象的创建过程时,我们发现callAdapter.adapt(okHttpCall)方法返回的是ExecutorCallbackCall对象,因此call.enqueue(new Callback<User>() {})方法最终调用的是ExecutorCallbackCall对象的enqueue方法。
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override
public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
if (delegate.isCanceled()) {
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override
public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
}
}
在ExecutorCallbackCall的enqueue方法中,调用了delegate.enqueue(new Callback<T>() {}),其中delegate是传入的OkHttpCall对象。OkHttpCall类实现了Call接口,使用OkHttp发送实际的网络请求:
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T> serviceMethod;
private okhttp3.Call rawCall;
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
Throwable failure;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
}
在OkHttpCall的enqueue方法中,调用了createRawCall方法创建OkHttp的RealCall对象,然后调用OkHttp的RealCall的enqueue方法,发起网络请求。在onResponse方法中调用parseResponse方法解析返回结果,然后调用callback的onResponse方法将结果传递给用户。在onFailure方法中调用callback的onFailure方法将错误信息传递给用户。
createRawCall方法
createRawCall方法用于创建实际用于请求的OkHttp Call对象:
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
parseResponse方法
parseResponse方法用于解析OkHttp返回的Response对象,并将其转换为Retrofit的Response对象:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
catchingBody.throwIfCaught();
throw e;
}
}
parseResponse方法通过serviceMethod.toResponse方法将ResponseBody转换为T类型的对象,然后返回一个Response对象:
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
总结
在Retrofit中,发起网络请求的过程涉及多个步骤和对象的协作:
- 调用接口方法创建
Call对象,并调用enqueue方法发起异步请求。 - 通过
CallAdapter适配,将请求委托给ExecutorCallbackCall,以便在指定的执行器中处理回调。 ExecutorCallbackCall将请求进一步委托给OkHttpCall,后者使用OkHttp发送实际的网络请求。- 请求的响应或失败通过回调传递给用户,在回调中进行相应的处理。
通过这种方式,Retrofit实现了简洁且灵活的网络请求处理机制,方便开发者在应用中集成网络请求功能。