04_Retrofit工作流程-发起请求过程分析

150 阅读3分钟

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();
        }
    }
}

ExecutorCallbackCallenqueue方法中,调用了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();
                }
            }
        });
    }
}

OkHttpCallenqueue方法中,调用了createRawCall方法创建OkHttp的RealCall对象,然后调用OkHttp的RealCallenqueue方法,发起网络请求。在onResponse方法中调用parseResponse方法解析返回结果,然后调用callbackonResponse方法将结果传递给用户。在onFailure方法中调用callbackonFailure方法将错误信息传递给用户。

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对象,并将其转换为RetrofitResponse对象:

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中,发起网络请求的过程涉及多个步骤和对象的协作:

  1. 调用接口方法创建Call对象,并调用enqueue方法发起异步请求。
  2. 通过CallAdapter适配,将请求委托给ExecutorCallbackCall,以便在指定的执行器中处理回调。
  3. ExecutorCallbackCall将请求进一步委托给OkHttpCall,后者使用OkHttp发送实际的网络请求。
  4. 请求的响应或失败通过回调传递给用户,在回调中进行相应的处理。

通过这种方式,Retrofit实现了简洁且灵活的网络请求处理机制,方便开发者在应用中集成网络请求功能。