Retrofit 源码解析

  • 概述
  • 基本使用
  • 源码分析
    • 1. 构造 Retrofit 对象
    • 2. 创建服务接口对象
    • 3. 解析服务方法上的注解
  • 通过服务方法发起网络请求
  • CallAdapter
  • Converter
  • ParameterHandler
  • OkHttpCall
  • 总结
  • 参考

源码基于 com.squareup.retrofit2:retrofit:2.9.0。

概述

  • Builder 模式构建;
  • 动态代理;
  • 自定义注解;
  • 默认只能将响应体转换为 OkHttp 中的 ResponseBody。

Retrofit 只负责生产能做网络请求的工作对象,他有点像一个工厂,只提供产品,工厂本身不处理网络请求,产品才能处理网络请求。

Retrofit

基本使用

public interface GitHubService {
    @GET("/users/{user}")
    Call getUser(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

GitHubService service = retrofit.create(GitHubService.class);
Call userCall = service.getUser("square");
userCall.enqueue(new Callback() {
    @Override
    public void onResponse(Call call, Response response) {
        GitHubUser user = response.body();
    }

    @Override
    public void onFailure(Call call, Throwable t) {
    }
});

源码分析

Retrofit 整体流程如下:

Retrofit 流程

1. 构造 Retrofit 对象

// Retrofit.java
public static final class Builder {
    Builder(Platform platform) {
        this.platform = platform;
    }

    public Builder() {
        this(Platform.get());
    }

    public Retrofit build() {
        if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
        }

        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null) {
            callFactory = new OkHttpClient();
        }

        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
            callbackExecutor = platform.defaultCallbackExecutor();
        }

        // Make a defensive copy of the adapters and add the default Call adapter.
        List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
        callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

        // Make a defensive copy of the converters.
        List converterFactories =
            new ArrayList<>(1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

        // Add the built-in converter factory first. This prevents overriding its behavior but also
        // ensures correct behavior when using converters that consume all types.
        converterFactories.add(new BuiltInConverters());
        converterFactories.addAll(this.converterFactories);
        converterFactories.addAll(platform.defaultConverterFactories());

        return new Retrofit(
            callFactory,
            baseUrl,
            unmodifiableList(converterFactories),
            unmodifiableList(callAdapterFactories),
            callbackExecutor,
            validateEagerly);
    }
}
  1. url 不能为空;
  2. callFactory 默认为 OkHttpClient;
  3. 支持 Java 和 Android 平台。
// Platform.java
private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android()
        : new Platform(true);
}

2. 创建服务接口对象

// Retrofit.java
public  T create(final Class 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 {
                // If the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
}

private void validateServiceInterface(Class service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }

    Deque> check = new ArrayDeque<>(1);
    check.add(service);
    while (!check.isEmpty()) {
      Class candidate = check.removeFirst();
      if (candidate.getTypeParameters().length != 0) {
        // ...
        throw new IllegalArgumentException(message.toString());
      }
      // 检查父接口
      Collections.addAll(check, candidate.getInterfaces());
    }

    //是否提前加载服务方法
    if (validateEagerly) {
      Platform platform = Platform.get();
      for (Method method : service.getDeclaredMethods()) {
        if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
          loadServiceMethod(method);
        }
      }
    }
}
  1. 服务类必须是接口,且不支持泛型;
  2. 判断是否预加载服务方法;
  3. 通过动态代理实例化服务接口对象。

3. 解析服务方法上的注解

// Retrofit.java
public  T create(final Class 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 {
                    // If the method is a method from Object then defer to normal invocation.
                    if (method.getDeclaringClass() == Object.class) {
                        return method.invoke(this, args);
                    }
                    args = args != null ? args : emptyArgs;
                    return platform.isDefaultMethod(method)
                        ? platform.invokeDefaultMethod(method, service, proxy, args)
                        : loadServiceMethod(method).invoke(args);
                }
            });
}

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

通过动态对象调用服务方法。

  1. 服务方法存在,直接返回;
  2. 服务方法不存在,解析服务方法,并添加到缓存。
// ServiceMethod.java
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);
}
  1. 根据注解解析出请求方法,相对地址和请求头等数据,并包装成 RequestFactory;
  2. 服务方法返回类型不能是 void,类型变量和通配符类型;
  3. 返回 ServiceMethod 实例。
// RequestFactory.java
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, 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);
}

private void parseMethodAnnotation(Annotation annotation) {
    if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
    } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
    } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
    } else if (annotation instanceof retrofit2.http.Headers) {
        headers = parseHeaders(headersToParse);
    } else if (annotation instanceof Multipart) {
        isMultipart = true;
    } else if (annotation instanceof FormUrlEncoded) {
        isFormEncoded = true;
    }
}

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
    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);
}
  1. 根据具体的注解类型解析出数据;
// HttpServiceMethod.java
static  HttpServiceMethod parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // ...
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
        // Kotlin 协程方法
    } else {
        // Call,Observable
        adapterType = method.getGenericReturnType();
    }
    // 查找能处理此请求的 CallAdapter
    CallAdapter callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    // Call 中的 GitHubUser
    Type responseType = callAdapter.responseType();
    // 查找能处理此请求的响应转换器
    Converter responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
        return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      // ...
    } else {
      // ...
    }
}
  1. 适配 CallAdapter;
  2. 查找能处理此返回类型的 ConverterFactory。默认的 BuiltInConverters 只能处理 ResponseBody 和 Void 类型;
  3. 返回 CallAdapted 对象。

通过服务方法发起网络请求

abstract class HttpServiceMethod 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);

    static final class CallAdapted extends HttpServiceMethod {
        private final CallAdapter callAdapter;

        @Override
        protected ReturnT adapt(Call call, Object[] args) {
            // DefaultCallAdapterFactory$CallAdapter
            return callAdapter.adapt(call);
        }
    }
}

final class DefaultCallAdapterFactory extends CallAdapter.Factory {

    @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");
        }
        final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

        final Executor executor =
            Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
                ? null
                : callbackExecutor;

        return new CallAdapter>() {
            @Override
            public Type responseType() {
                return responseType;
            }

            @Override
            public Call adapt(Call call) {
                return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
            }
        };
    }

    static final class ExecutorCallbackCall implements Call {

        @Override
        public void enqueue(final Callback callback) {
            // delegate 是 retrofit2.OkHttpCall
            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));
                    }
                });
        }

        @Override
        public Response execute() throws IOException {
            return delegate.execute();
        }
    }
}
 
 
  1. 适配成 retrofit2.Call、Single等;
  2. 通过 retrofit2.OkHttpCall 发起 http 请求;
  3. 响应消息回调。

CallAdapter

负责把 Retrofit 中执行网络请求的 Call 对象,转换为接口中定义的 Call 对象(eg:Observable< User >,Flowable< User >)。

public interface CallAdapter {

    Type responseType();
    T adapt(Call call);

    abstract class Factory {
        public abstract @Nullable CallAdapter get(
            Type returnType, Annotation[] annotations, Retrofit retrofit);

        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
            return Utils.getParameterUpperBound(index, type);
        }

        protected static Class getRawType(Type type) {
            return Utils.getRawType(type);
        }
    }
}

Retrofit 默认实现了两个 CallAdapter:

  1. DefaultCallAdapterFactory
  2. CompletableFutureCallAdapterFactory

Converter

负责把服务器返回的数据(JSON、XML、二进制或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象。

public interface Converter {
    T convert(F value) throws IOException;

    abstract class Factory {
        public @Nullable Converter responseBodyConverter(
            Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }

        public @Nullable Converter requestBodyConverter(
            Type type, Annotation[] parameterAnnotations,
                Annotation[] methodAnnotations, Retrofit retrofit) {
            return null;
        }

        public @Nullable Converter stringConverter(
            Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }

        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
            return Utils.getParameterUpperBound(index, type);
        }

        protected static Class getRawType(Type type) {
            return Utils.getRawType(type);
        }
    }
}

Converter.Factory 的默认实现类有 BuiltInConvertersOptionalConverterFactory

final class BuiltInConverters extends Converter.Factory {
    @Override
    public @Nullable Converter responseBodyConverter(
        Type type, Annotation[] annotations, Retrofit retrofit) {
        if (type == ResponseBody.class) {
            return Utils.isAnnotationPresent(annotations, Streaming.class)
                ? StreamingResponseBodyConverter.INSTANCE
                : BufferingResponseBodyConverter.INSTANCE;
        }
        if (type == Void.class) {
            return VoidResponseBodyConverter.INSTANCE;
        }
        if (checkForKotlinUnit) {
            try {
                if (type == Unit.class) {
                return UnitResponseBodyConverter.INSTANCE;
                }
            } catch (NoClassDefFoundError ignored) {
                checkForKotlinUnit = false;
            }
        }
        return null;
    }
}

ParameterHandler

负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数。

OkHttpCall

final class OkHttpCall implements Call {

    @Override
    public void enqueue(final Callback callback) {

        synchronized (this) {
            if (executed) throw new IllegalStateException("Already executed.");
            executed = true;

            call = rawCall;
            failure = creationFailure;
            if (call == null && failure == null) {
                call = rawCall = createRawCall();
            }
        }

        call.enqueue(
            new okhttp3.Callback() {
                @Override
                public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                    Response response = parseResponse(rawResponse);
                    callback.onResponse(OkHttpCall.this, response);
                }
            });
    }

    Response parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();

        // Remove the body's source (the only stateful object) so we can pass the response along.
        rawResponse =
            rawResponse
                .newBuilder()
                .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
                .build();

        ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
        T body = responseConverter.convert(catchingBody);
        return Response.success(body, rawResponse);
    }
}

总结

  1. 构造 retrofit,核心参数有 baseurl,callFactory(默认 okhttpclient),converterFactories,adapterFactories 和 excallbackExecutor。
  2. 通过 Retrofit#create() 方法获取接口的实现类,运用了 Java 的动态代技术。
  3. 调用服务方法时会先实例化 ServiceMethod。ServiceMethod 通过解析服务方法上的注解
    在 invoke 方法内部,拿到我们所声明的注解以及实参等,构造 ServiceMethod。ServiceMethod 中解析了大量的信息,最后可以通过 toRequest 构造出 okhttp3.Request 对象。有了 okhttp3.Request 对象就可以很自然的构建出 okhttp3.call,最后 calladapter 对 Call 进行装饰返回。
    拿到 Call 就可以执行 enqueue 或者 execute 方法了

responseBodyConverter 主要是对应@Body 注解,完成 ResponseBody 到实际的返回类型的转化,这个类型对应 Call< XXX >里面的泛型,其实@Part 等注解也会需要 responseBodyConverter,只不过我们的参数类型都是 RequestBody,由默认的 converter 处理了。
requestBodyConverter 完成对象到 RequestBody 的构造。
一定要注意,检查 type 如果不是自己能处理的类型,记得 return null (因为可以添加多个,你不能处理 return null ,还会去遍历后面的 converter).

参考

[1] 从架构角度看 Retrofit 的作用、原理和启示
[2] 拆轮子系列:拆 Retrofit

你可能感兴趣的:(Retrofit 源码解析)