}
GitHubService service = retrofit.create(GitHubService.class);
之后,我们调用 service
中对应的方法,就可以获取到 Call 对象了。
通过对 Call 对象调用 enqueue
就可以实现对请求的异步调用,而通过 execute
方法则可以实现请求的同步调用。
Retrofit 对象的构建
Retrofit 采用了 Builder 模式进行了构建,在 Builder 中可以进行非常多的配置,其中可以对 baseUrl
、okhttpClient
、converterFactory
、callAdapterFactory
等进行设置。
这里没什么特别的,都是一些简单的赋值,就不再关注了,我们只需要看看最后 Retrofit 被传入了哪些参数。它最后调用了下面这个构造函数对参数进行了初始化。
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
Service 对象的创建
动态代理创建 Service 代理类
接着我们看到自己定义的 interface
是如何仅仅靠传递 class
给 Retrofit.create
就能实现实例的获取的,它明明只是个接口呀?
public T create(final Class service) {
// 对 Service 的接口进行检测
validateServiceInterface(service);
// 通过动态代理构建代理对象
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// Object 类的方法照常调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 如果是对应平台本身的类就有的方法,照常调用
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 否则通过 loadServiceMethod 方法获取到对应 Method 并 invoke
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
可以看到,实际上 Service
对象的获取是通过动态代理实现的。这里首先通过 validateServiceInterface
方法对接口进行了检测,之后通过动态代理对该接口进行了代理。
对于 Object
类本身独有以及对应平台本身就存在的方法,就照常调用,否则通过 loadServiceMethod
对 Service
中对应的 Method
对象进行处理,之后对其调用 invoke
方法。
这里说明了 Retrofit
不是在创建 Service
接口对应对象时就立即对所有该接口中的所有方法都进行注解的解析,而是采用了在方法被调用时才进行注解的解析这种懒加载的思想。
接着我们看看 validateServiceInterface
方法:
private void validateServiceInterface(Class<?> service) { // 判断是否是接口 if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); } // 判断该接口及其继承的所有接口是否包含了范型参数,如果包含则抛出异常 Deque
首先,这个方法对 service
进行了检测,保证了它是一个接口并且它和它继承的类中没有范型参数。
之后如果在 Retrofit 创建时设置 validateEagerly
为 true 的话,会对 Service 中所有非平台独有且非static的方法通过 loadServiceMethod
方法提前进行处理
Service 中方法的解析
那么我们来看看 loadServiceMethod
究竟做了些什么:
ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
首先它会采用 Double Check 的方式尝试从 serviceMethodCache
缓存中获取 ServiceMethod
对象,如果获取不到则通过 ServiceMethod.parseAnnotations
方法对该 Method 的注解进行处理并将得到的 ServiceMethod
对象加入了缓存。
也就是说为了避免多次对方法的注解进行处理,Retrofit 采用了一个 serviceMethodCache
对解析后的 ServiceMethod
进行缓存。
接着我们就来看看,parseAnnotations
方法是如何对方法的注解进行解析的。
static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
“Method return type must not include a type variable or wildcard: %s”, returnType);
}
if (returnType == void.class) {
throw methodError(method, “Service methods cannot return void.”);
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
这里先通过 RequestFactory.parseAnnotations
方法对注解解析并获得了一个 RequestFactory
对象。
之后又通过 HttpServiceMethod.parseAnnotations
方法传入了 requestFactory
继续进行注解的解析并获得 ServiceMethod
对象
注解解析
我们先看看 RequestFactory.parseAnnotations
:
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
它把 Method
传入 Builder
从而构建了一个新的 RequestFactory
:
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
Builder 中通过反射获取到method
所包含的注解、参数包含的范型以及参数的注解。
接着看看 build
方法:
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
// 遍历方法注解对每个注解进行解析
parseMethodAnnotation(annotation);
}
// …异常的处理
// 对参数进行解析
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
// … 异常的处理
return new RequestFactory(this);
}
在 build 方法中主要是对方法的每个注解调用了 parseMethodAnnotation
进行了解析,并且对每个参数调用了 parseParamter
方法解析为了 ParamterHandler
对象。
parseMethodAnnotation
的代码如下:
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath(“DELETE”, ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath(“GET”, ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath(“HEAD”, ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath(“PATCH”, ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath(“POST”, ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath(“PUT”, ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath(“OPTIONS”, ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, “@Headers annotation is empty.”);
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, “Only one encoding annotation is allowed.”);
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, “Only one encoding annotation is allowed.”);
}
isFormEncoded = true;
}
}
这里实际上就是对每一种 HTTP 所支持的类型进行了支持,获取到了对应注解的中的 url,并调用parseHttpMethodAndPath
进行处理,同时对 Headers 注解则是通过 parseHeaders
进行了处理。
对 Http 请求方式和 Path 的处理
对于 Method 和 Path,通过 parseHttpMethodAndPath
进行了参数的赋值:
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError(method, “Only one HTTP method is allowed. Found: %s and %s.”,
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
int question = value.indexOf(‘?’);
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(method, "URL query string “%s” must not have replace block. "+ “For dynamic query parameters use @Query.”, queryParams);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
这里实际上就是对不同 HTTP 请求方式和 Path 进行了赋值,同时通过正则表达式保证了这个接口的 Path 中没有包含参数。
对 Headers 的处理
private Headers parseHeaders(String[] headers) {
Headers.Builder builder = new Headers.Builder();
for (String header : headers) {
int colon = header.indexOf(‘:’);
if (colon == -1 || colon == 0 || colon == header.length() - 1) {
throw methodError(method,
“@Headers value must be in the form “Name: Value”. Found: “%s””, header);
}
String headerName = header.substring(0, colon);
String headerValue = header.substring(colon + 1).trim();
if (“Content-Type”.equalsIgnoreCase(headerName)) {
try {
contentType = MediaType.get(headerValue);
} catch (IllegalArgumentException e) {
throw methodError(method, e, “Malformed content type: %s”, headerValue);
}
} else {
builder.add(headerName, headerValue);
}
}
return builder.build();
}
而对于 Headers 则是将传递进来的 Headers
列表解析为了对应的 Headers
对象。
对方法参数的处理
最后我们看看对方法参数的处理:
private @Nullable ParameterHandler<?> parseParameter( int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) { ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
// 对每个注解通过 parseParameterAnnotation 进行解析
ParameterHandler<?> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(method, p,
“Multiple Retrofit annotations found, only one allowed.”);
}
result = annotationAction;
}
}
if (result == null) {
// 在协程的情况下对进行特殊处理
if (allowContinuation) {
try {
if (Utils.getRawType(parameterType) == Continuation.class) {
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, “No Retrofit annotation found.”);
}
return result;
}
而 parseParamterAnnotation
方法的代码太长了,这里就不再贴了,它对方法的每个注解都进行了独有的处理,并返回了对应的 ParamterHandler
。
可以发现,RequestFactory.parseAnnotations
的主要作用就是完成对方法注解信息的解析,从而用于产生对应的 Request
。
ServiceMethod 的创建
之后我们接着看看 HttpServiceMethod.parseAnnotations
:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
// 如果方法是 kotlin 中的 suspend 方法
Type[] parameterTypes = method.getGenericParameterTypes();
// 获取 Continuation 的范型参数,它就是 suspend 方法的返回值类型
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
// 如果 Continuation 的范型参数是 Response,则说明它需要的是 Response,那么将 continuationWantsResponse 置为 true;
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
// 否则获取方法返回值的范型参数,即为请求需要的返回值的类型
adapterType = method.getGenericReturnType();
}
// 通过 createCallAdapter 方法创建 CallAdapter 对象
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(method, “'”
- getRawType(responseType).getName()
- “’ is not a valid response body type. Did you mean ResponseBody?”);
}
if (responseType == Response.class) {
throw methodError(method, “Response must include generic type (e.g., Response)”);
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals(“HEAD”) && !Void.class.equals(responseType)) {
throw methodError(method, “HEAD method must use Void as response type.”);
}
// 通过 createResponseConverter 方法创建 Converter对象
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 不是suspend方法的话则直接创建并返回一个 CallAdapted 对象
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call>) callAdapter,
continuationBodyNullable);
}
}
这里的代码非常非常长,大致可归纳为下面的步骤:
1. 如果这个方法是 Kotlin 中的 suspend 方法,由于由协程实现,因此需要获取
Continuation
的范型参数,这个参数就是请求返回值的真正类型。
2. 如果suspend
方法返回值是Response
,则说明它需要的是 Response 而不是具体的类型,那么将continuationWantsResponse
置为 true;
3. 如果不是suspend
方法,则返回值的范型参数的类型就是请求返回值的真正类型(Call<ReturnType>
则ReturnType
才是真正经过转换后需要的类型)。
4. 通过createCallAdapter
方法创建CallAdapter
对象,它是用于将Call<ResponseT>
对象适配为需要的类型ReturnT
对象的。
5. 拿到CallAdapter
后,获取到了Response
的类型,并进行了校验。
6. 通过createResponseConverter
方法获取Converter
对象,它可以完成从ResponseBody
到Response
类型ResponseT
的转换。
7. 如果并非 Kotlin 的 suspend 方法,则直接传入CallAdapter
及 Converter,创建CallAdapted
对象。
8. 否则根据 suspend 方法需要的是Response
还是具体的类型,分别返回SuspendForResponse
和SuspendForBody
对象。
可以发现,新版的 Retrofit 对 Kotlin 的协程进行了支持。HttpServiceMethod.parseAnnotations
的主要作用就是创建 CallAdapter
以及 Converter 对象,并构建对应 HttpServiceMethod
。
CallAdapter
CallAdapter
是用于将Call<R>
对象适配为需要的类型 T 对象的。它的声明如下:
public interface CallAdapter<R, T> {
// 返回 Response 的类型
Type responseType();
// 将 Call 转换为 T 类型
T adapt(Call call);
}
我们先看看 createCallAdapter
方法是如何对它创建的:
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, “Unable to create call adapter for %s”, returnType);
}
}
它调用了 retrofit.callAdapter
方法:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
之后调用到 retrofit.nextCallAdapter
方法:
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
Objects.requireNonNull(returnType, “returnType == null”);
Objects.requireNonNull(annotations, “annotations == null”);
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
// 遍历 callAdapterFactories,尝试创建 CallAdapter
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
// …不存在对应的 CallAdapterFactory,抛出异常
}
这里实际上是遍历了创建 Retrofit 对象时传递的 CallAdapter.Factory
列表尝试去创建 CallAdapter
。如果这些 CallAdapter.Factory
都无法处理这个对应的 returnType
以及 annotations
的话,则会抛出异常。(前面 Factory 的优先级更高)
Retrofit 中有一个默认的 CallAdapter
工厂 DefaultCallAdapterFactory
,它的优先级比所有自定义工厂要低,它在创建时会传入一个 Executor
,我们可以看到它的 get 方法:
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call or Call<? extends Foo>"); } final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType); final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null: callbackExecutor; return new CallAdapter
可以看到,在没有 Executor
时,它不对 Call 进行修改,在有指定 Executor 时,则会将其包装为 ExecutorCallbackCall
。一般来说这个 Executor 就是创建 Retrofit 时指定的 callbackExecutor
。
这个 callbackExecutor
实际上是用来指定调用 Callback
的线程的,从而使得 Callback
并不一定是在主线程被回调:
static final class ExecutorCallbackCall implements Call {
final Executor callbackExecutor;
final Call delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback callback) {
Objects.requireNonNull(callback, “callback == null”);
// 对 Callback 进行了包装,通过 callbackExecutor 进行回调
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(() -> {
if (delegate.isCanceled()) {
// Emulate OkHttp’s behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException(“Canceled”));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
});
}
@Override public void onFailure(Call call, final Throwable t) {
callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
// …
}
可以看到,这里实际上只是对 Callback 进行了包装,通过传递的 Executor 进行回调,从而对 callbackExecutor
进行支持。
Converter
接着我们看看 Converter
类,它是一个接口,用于将类型 F 的数据转换为类型 T:
public interface Converter<F, T> {
@Nullable T convert(F value) throws IOException;
// …
}
接着我们看看 createResponseConverter
是如何对它进行创建的:
private static Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, “Unable to create converter for %s”, responseType);
}
}
转调到了 retrofit.responseBodyConverter
:
public Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
转调到了 nextResponseBodyConverter
:
public Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
Objects.requireNonNull(type, “type == null”);
Objects.requireNonNull(annotations, “annotations == null”);
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
// 没有找到对应的 ConverterFactory 进行处理,抛出异常
}
可以看到,这里与 CallAdapter
工厂类似,遍历创建 Retrofit 时传入的 Converter.Factory
列表,尝试进行创建,如果没有工厂能对其进行处理,抛出异常。(前面 Factory 的优先级更高)
Retrofit
中内置了两个 Converter.Factory
,分别是 BuiltInConverters
以及 OptionalConverterFactory
。
其中 BuiltInConverters
的优先级比所有自定义工厂要高,以避免其他工厂覆盖它的方法,而 OptionalConverterFactory
的优先级比所有自定义工厂的优先级更低。
BuiltInConverters
中实现了多个转换器如将 ResponseBody
转换为 Void 或 Unit,将 Object 转换为 String 等。
OptionalConverterFactory
是通过 platform 获取到的 defaultConverterFactories
,它是为了支持 Java 8 的 Optional 而实现的,Optional 是 Java 8 引入的用来解决空指针异常的类。
ServiceMethod
接着我们看看之前创建的 ServiceMethod
类,它是一个抽象类,需要子类对 invoke 方法进行实现。
abstract class ServiceMethod {
abstract @Nullable T invoke(Object[] args);
}
它的子类就是前面提到的 HttpServiceMethod
HttpServiceMethod
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod {
@Override final @Nullable ReturnT invoke(Object[] args) {
Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call call, Object[] args);
}
HttpServiceMethod
的 invoke 方法非常简单,它构造了一个 OkHttpCall
,然后通过 adapt 这个虚函数来实现对 Call 的转换。它的子类只需要实现 adapt 从而对 Call 进行转换即可。
它共有三个子类,首先就是并非使用协程的情况下的 CallAdapted
类,另外两个子类则是在使用协程的情况下为了配合协程的 SuspendForResponse
以及 SuspendForBody
类
CallAdapted
CallAdapted
类继承自 HttpServiceMethod
类,并通过传递进来的 CallAdapter
对 Call 进行了转换。
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call call, Object[] args) {
return callAdapter.adapt(call);
}
}
SuspendForResponse
SuspendForResponse
类首先根据传递进来的 Call 构造了一个参数为 Response<ResponseT>
的 Continuation
对象然后通过 Kotlin 实现的 awaitResponse
方法将 call 的 enqueue
异步回调过程封装为了一个 suspend 的函数。
static final class SuspendForResponse extends HttpServiceMethod<ResponseT, Object> {
private final CallAdapter<ResponseT, Call> callAdapter;
SuspendForResponse(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, Call> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected Object adapt(Call call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<Response> continuation =
(Continuation<Response>) args[args.length - 1];
// See SuspendForBody for explanation about this try/catch.
try {
return KotlinExtensions.awaitResponse(call, continuation);
} catch (Exception e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
awaitResponse
方法如下:
suspend fun Call.awaitResponse(): Response {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
continuation.resume(response)
}
override fun onFailure(call: Call, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
可以看到,分别通过在 onResponse
和 onFailure
中调用 continuation.resume
和 continuation.resumeWithException
从而对协程进行支持。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/eeb64ca40d15553c14129c7fc4dfa1cd.jpeg)
尾声
一转眼时间真的过的飞快。我们各奔东西,也各自踏上了自己的旅途,但是即使多年不见,也因为这份情谊我们依旧如从前那般“亲密”。不忘初心方得始终。加油吧,程序员们,在我看来35岁,40岁从来不是危机,只要永远不要忘记自己为何踏上征程!
为了让更多在学习中或者最近要准备面试的朋友们看到这篇文章,希望你们能多多评论,点赞+转发!
再次感谢所有给我提供过题目的朋友们,感谢一路有你!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
外链图片转存中…(img-1hLtXqGx-1713601159885)]
[外链图片转存中…(img-vs8dbm8c-1713601159886)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/eeb64ca40d15553c14129c7fc4dfa1cd.jpeg)
尾声
一转眼时间真的过的飞快。我们各奔东西,也各自踏上了自己的旅途,但是即使多年不见,也因为这份情谊我们依旧如从前那般“亲密”。不忘初心方得始终。加油吧,程序员们,在我看来35岁,40岁从来不是危机,只要永远不要忘记自己为何踏上征程!
为了让更多在学习中或者最近要准备面试的朋友们看到这篇文章,希望你们能多多评论,点赞+转发!
再次感谢所有给我提供过题目的朋友们,感谢一路有你!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!