Retrofit 源码分析

作者: 慌不要慌 | 来源:发表于2016-08-09 20:51 被阅读631次

    最近非常流行 Retrofit+RxJava+OkHttp 这一整套的网络请求和异步操作的开源框架,从 Jake Wharton 的 Github 主页也能看出其趋势。

    Retrofit+RxJava+OkHttp.png

    本文主要介绍 Retrofit 的基本原理,基于 2.1.0 版本的源码。

    1. 基本用法

    1.1 定义 API 接口

    Retrofit 的使用非常简单,先来看一个 官网 上的示例代码。

    public interface GitHubService {
        @GET("users/{user}/repos")
        Call<List<Repo>> listRepos(@Path("user") String user);
    }
    

    官方的解释是

    Retrofit turns your HTTP API into a Java interface.

    首先定义了一个 API 接口 GitHubService,包含 HTTP 请求的方法 GET 和参数 user,及成功后的返回类型 List<Repo>,方法和参数由注解声明,非常清晰。

    1.2 创建 Retrofit 对象并生成 API 实例

    Retrofit retrofit = new Retrofit.Builder()
          .baseUrl("https://api.github.com/")
          .addConverterFactory(GsonConverterFactory.create())
          .build();
          
    GitHubService service = retrofit.create(GitHubService.class);
    

    然后创建一个 Retrofit 对象,这里采用 Builder 模式,传入 baseUrlConverterFactory 等参数,后面会讲到。

    通过 Retrofit 对象用动态代理的方式生成我们需要的 API 实例 GitHubService

    1.3 API 实例去请求服务

    Call<List<Repo>> repoCall = service.listRepos("danke77");
    

    用生成的 API 实例调用相应的方法,默认返回 Call<T>,然后调用 Call#execute 方法同步或调用 Call#enqueue 方法异步请求 HTTP。

    List<Repo> repos = repoCall.execute().body();
    

    请求返回的数据直接转化成了 List<Repo>,非常方便。

    如果要使用 RxJava,在创建 Retrofit 对象时要调用 addCallAdapterFactory(RxJavaCallAdapterFactory.create()),则返回类型会从 Call<T> 转换成 Observable<T>

    2. Retrofit

    2.1 build

    先看一下 Retrofit.Builder 类里的成员变量。

    private Platform platform;
    private okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private List<Converter.Factory> converterFactories = new ArrayList<>();
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    private Executor callbackExecutor;
    private boolean validateEagerly;
    

    Platform 提供了3个平台:Java8AndroidIOS,全都继承自 Platform,初始化时静态方法 Platform#findPlatform 会自动识别属于哪一个。

    private static Platform findPlatform() {
        try {
            Class.forName("android.os.Build");
            if (Build.VERSION.SDK_INT != 0) {
                return new Android();
            }
        } catch (ClassNotFoundException ignored) {
        }
        try {
            Class.forName("java.util.Optional");
            return new Java8();
        } catch (ClassNotFoundException ignored) {
        }
        try {
            Class.forName("org.robovm.apple.foundation.NSObject");
            return new IOS();
        } catch (ClassNotFoundException ignored) {
        }
        return new Platform();
    }
    

    通过 Retrofit.Builder#clientRetrofit.Builder#callFactory 可以自定义 OkHttpClient

    public Builder client(OkHttpClient client) {
        return callFactory(checkNotNull(client, "client == null"));
    }
    
    public Builder callFactory(okhttp3.Call.Factory factory) {
        this.callFactory = checkNotNull(factory, "factory == null");
        return this;
    }
    

    如果不指定 callFactory,则默认使用 OkHttpClient

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

    converterFactoriesadapterFactories 提供了2个工厂列表,用于用户自定义数据转换和类型转换,后面会详细说明。

    最后调用 Retrofit.Builder#build 创建一个 Retrofit 对象。

    public Retrofit build() {
        // ... configured values
        
        return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
              callbackExecutor, validateEagerly);
    }
    

    2.2 create

    public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);
        if (validateEagerly) {
            eagerlyValidateMethods(service);
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
              private final Platform platform = Platform.get();
    
              @Override public Object invoke(Object proxy, Method method, 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);
                  }
                  if (platform.isDefaultMethod(method)) {
                      return platform.invokeDefaultMethod(method, service, proxy, args);
                  }
                  ServiceMethod serviceMethod = loadServiceMethod(method);
                  OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                  return serviceMethod.callAdapter.adapt(okHttpCall);
              }
        });
    }
    

    首先调用 Utils.validateServiceInterface 去判断 service 是否是一个 Interface 且没有继承其他 Interface,否则抛非法参数异常。

    static <T> void validateServiceInterface(Class<T> service) {
        if (!service.isInterface()) {
            throw new IllegalArgumentException("API declarations must be interfaces.");
        }
        if (service.getInterfaces().length > 0) {
            throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
        }
    }
    

    如果 validateEagerlytrue,则会调用 eagerlyValidateMethods 方法,会去预加载 service 中的所有方法,默认为 false

    private void eagerlyValidateMethods(Class<?> service) {
        Platform platform = Platform.get();
        for (Method method : service.getDeclaredMethods()) {
            if (!platform.isDefaultMethod(method)) {
              loadServiceMethod(method);
            }
        }
    }
    

    然后就是通过动态代理生成 service。前两个 if 分支分别判断是否是 Object 的方法及 default 方法,后者除了 Java8 其他都是 false

    再看 loadServiceMethod

    ServiceMethod loadServiceMethod(Method method) {
        ServiceMethod result;
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = new ServiceMethod.Builder(this, method).build();
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }
    

    通过 serviceMethodCache 实现缓存机制,同一个 service 的同一个方法只会创建一次,生成 ServiceMethod 同时存入 Cache

    ServiceMethod 和需要的参数生成一个 OkHttpCall 对象。然后用 CallAdapter 将生成的 OkHttpCall 转换为我们需要的返回类型,这个后面会说到。

    3. ServiceMethod

    Adapts an invocation of an interface method into an HTTP call.

    ServiceMethod 的作用就是把一个 API 方法转换为一个 HTTP 调用。

    Retrofit#loadServiceMethod 方法中可以看出一个 API 方法对应一个 ServiceMethod

    GitHubService为例

    public interface GitHubService {
        @GET("users/{user}/repos")
        Call<List<Repo>> listRepos(@Path("user") String user);
    }
    

    @GET("users/{user}/repos")MethodAnnotations@Path("user") String userParameterAnnotationsCall<List<Repo>>CallAdapter

    3.1 ServiceMethod.Builder

    先看下 ServiceMethod.Builder 的构造函数

    public Builder(Retrofit retrofit, Method method) {
        this.retrofit = retrofit;
        this.method = method;
        this.methodAnnotations = method.getAnnotations();
        this.parameterTypes = method.getGenericParameterTypes();
        this.parameterAnnotationsArray = method.getParameterAnnotations(); 
    }
    

    传入 retrofitmethod 对象,通过 method 获取到方法注解 methodAnnotations、参数类型 parameterTypes 和参数注解 parameterAnnotationsArrayparameterAnnotationsArray是一个二维数组 Annotation[][],因为一个参数可以有多个注解。

    关键看 ServiceMethod.Builder#build 方法,会生成一个 ServiceMethod 对象,接下来按顺序解析。

    3.2 createCallAdapter

    callAdapter = createCallAdapter() 会遍历 adapterFactories,通过 API 方法的 annotationsreturnType 取到第一个符合条件的 CallAdapter

    for (int i = start, count = adapterFactories.size(); i < count; i++) {
        CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
        if (adapter != null) {
            return adapter;
        }
    }
    

    然后取到 responseType = callAdapter.responseType() 并进行判断,如果是 retrofit2.Response<T>okhttp3.Response 则抛异常,目前支持的有默认的 retrofit2.Call<T>,RxJava 的 rx.Observable,Java8 的 java.util.concurrent.CompletableFuture 和 Guava 的 com.google.common.util.concurrent.ListenableFuture

    3.3 createResponseConverter

    responseConverter = createResponseConverter() 会遍历 converterFactories,通过 API 方法的 annotationsresponseType 取到第一个符合条件的 Converter<ResponseBody, T>

    for (int i = start, count = converterFactories.size(); i < count; i++) {
        Converter<ResponseBody, ?> converter =
            converterFactories.get(i).responseBodyConverter(type, annotations, this);
        if (converter != null) {
            return (Converter<ResponseBody, T>) converter;
        }
    }
    

    3.4 parseMethodAnnotation

    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
    }
    

    遍历 API 方法的所有 annotations,如实例中的 @GET("users/{user}/repos"),根据所属类型和值解析成 HTTP 请求需要的数据。

    在 package retrofit2.http 下包含了所有的 Method AnnotationParameter Anootation

    DELETEGETHEADPATHCPOSTPUTOPTIONSHTTP 类型的 annotaion 会调用 parseHttpMethodAndPath,生成 httpMethodhasBodyrelativeUrlrelativeUrlParamNames

    retrofit2.http.Headers 类型的 annotaion 会调用 parseHeaders,生成 headers

    MultipartFormUrlEncoded 类型的 annotaion 分别生成 isMultipartisFormEncoded,两者互斥,不能同时为 true,否则会抛异常。

    然后对生成的部分参数检查,httpMethod 不能为空,如果 hasBodyfalse,则 isMultipartisFormEncoded 必须也为 false,否则会抛异常。

    if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
    }
    
    if (!hasBody) {
        if (isMultipart) {
            throw methodError(
                "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
            throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
                + "request body (e.g., @POST).");
        }
    }
    

    3.5 parseParameterAnnotation

    int parameterCount = parameterAnnotationsArray.length;
    parameterHandlers = new ParameterHandler<?>[parameterCount];
    for (int p = 0; p < parameterCount; p++) {
        ...  
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
    }
    

    遍历每个参数的 parameterAnnotations,如实例中的 @Path("user") String user,根据所属类型和值解析成对应的 ParameterHandler,每个 Parameter Anootation 类型都有对应的 ParameterHandler,且每个参数只能有一个 ParameterHandler

    可以看下 parseParameter 的逻辑

    private ParameterHandler<?> parseParameter(
            int p, Type parameterType, Annotation[] annotations) {
        ParameterHandler<?> result = null;
        for (Annotation annotation : annotations) {
            ParameterHandler<?> annotationAction = parseParameterAnnotation(
                p, parameterType, annotations, annotation);
    
            if (annotationAction == null) {
                continue;
            }
    
            if (result != null) {
                throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
            }
    
            result = annotationAction;
        }
    
        if (result == null) {
            throw parameterError(p, "No Retrofit annotation found.");
        }
    
        return result;
    }
    

    关键在 parseParameterAnnotation,根据 annotation 的类型并做参数校验,会生成不同的 ParameterHandler,如 RelativeUrl

    if (type == HttpUrl.class
        || type == String.class
        || type == URI.class
        || (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
        return new ParameterHandler.RelativeUrl();
    } else {
        throw parameterError(p, "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
    }
    

    由于 Retrofit 不依赖 Android SDK,判断 type 时无法获取到 android.net.Uri.class,因此采用了 "android.net.Uri".equals(((Class<?>) type).getName()) 的技巧。

    每个 Parameter Anootation 都会对应一个 ParameterHandler,如 static final class Path<T> extends ParameterHandler<T>,它们都实现了 ParameterHandler<T>

    ParameterAnnotation ? extends ParameterHandler
    Url RelativeUrl
    Path Path
    Query Query
    QueryMap QueryMap
    Header Header
    HeaderMap HeaderMap
    Field Field
    FieldMap FieldMap
    Part Part
    PartMap PartMap
    Body Body

    每种 ParameterHandler 都通过 Converter<F, T> 将我们的传参类型转化成 RequestBuilder 需要的类型,并设置其参数。举个例子

    static final class Query<T> extends ParameterHandler<T> {
        private final String name;
        private final Converter<T, String> valueConverter;
        private final boolean encoded;
    
        Query(String name, Converter<T, String> valueConverter, boolean encoded) {
            this.name = checkNotNull(name, "name == null");
            this.valueConverter = valueConverter;
            this.encoded = encoded;
        }
    
        @Override void apply(RequestBuilder builder, T value) throws IOException {
            if (value == null) return; // Skip null values.
            builder.addQueryParam(name, valueConverter.convert(value), encoded);
        }
    }
    

    valueConverter.convert 将我们的传参类型 T 转换成 String,并设置到 RequestBuilder 中。其他的配置也是按同样的方式。

    4. OkHttpCall

    OkHttpCall 实现了 retrofit2.Call<T>,看下它的构造函数,传入 ServiceMethod 和请求参数。

    OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
    }
    

    4.1 createRawCall

    先看下 OkHttpCall#createRawCall

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

    将已经生成的 serviceMethod 通过 toRequest(args) 转成一个 okhttp3.Request 对象。再用创建 Retrofit 时指定的 okhttp3.Call.Factory 创建一个 okhttp3.Call,这里如果不指定 okhttp3.Call.Factory,则默认是 okhttp3.OkHttpClient

    ServiceMethod#toRequest 方法中,用 method 相关的配置生成一个 retrofit2.RequestBuilder 后,再用之前准备好的 parameterHandlers 处理每一个参数,最后生成一个 okhttp3.Request

    /** Builds an HTTP request from method arguments. */
    Request toRequest(Object... args) throws IOException {
        RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart);
    
        @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
        ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
    
        // ... 校验
        
        for (int p = 0; p < argumentCount; p++) {
            handlers[p].apply(requestBuilder, args[p]);
        }
    
        return requestBuilder.build();
    }
    

    4.2 execute

    okhttp3.Call#execute 用于同步请求 HTTP,线程会被阻塞,请求成功后返回我们指定的数据类型。

    @Override public Response<T> execute() throws IOException {
        okhttp3.Call call;
    
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already executed.");
            executed = true;
    
            if (creationFailure != null) {
                if (creationFailure instanceof IOException) {
                    throw (IOException) creationFailure;
                } else {
                    throw (RuntimeException) creationFailure;
                }
            }
    
            call = rawCall;
            if (call == null) {
                try {
                    call = rawCall = createRawCall();
                } catch (IOException | RuntimeException e) {
                    creationFailure = e;
                    throw e;
                }
            }
        }
    
        if (canceled) {
            call.cancel();
        }
    
        return parseResponse(call.execute());
    }
    

    首先检查 okhttp3.Call 是否已被执行。

    一个 okhttp3.Call 只能被执行一次,可以调用 OkHttpCall#clone 重新创建一个新的相同配置的 HTTP 请求。

    @Override public OkHttpCall<T> clone() {
        return new OkHttpCall<>(serviceMethod, args);
    }
    

    然后检查并创建 okhttp3.Call,调用 okhttp3.Call#execute 执行同步请求。

    最后调用 parsePesponse 将返回的 okhttp3.Response 解析成我们需要的数据。

    Response<T> 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();
    
        int code = rawResponse.code();
        // ... 状态码检查
    
        ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
        try {
            T body = serviceMethod.toResponse(catchingBody);
            return Response.success(body, rawResponse);
        } catch (RuntimeException e) {
            // If the underlying source threw an exception, propagate that rather than indicating it was
            // a runtime exception.
            catchingBody.throwIfCaught();
            throw e;
        }
    }
    

    okhttp3.Response 进行一些状态码检查后调用 ServiceMethod#toResponse 生成我们需要的数据类型。这里就用到了我们之前准备好的 responseConverter。最后封装成一个 retrofit2.Response<T>,包含了原始的 rawResponse、我们需要的 bodyerrorBody,我们取需要的数据。

    4.3 enqueue

    okhttp3.Call#enqueueokhttp3.Call#execute 流程类似,异步请求 HTTP,然后将回调都交给 retrofit2.Callback<T> 处理。

    看下 retrofit2.Callback#onFailure 的注释

    Invoked when a network exception occurred talking to the server or when an unexpected exception occurred creating the request or processing the response.

    这里 retrofit2.Callback#onFailure 除了处理网络异常外,还会处理创建网络请求和解析数据的异常,在回调中处理,而不是直接 crash,这点做的非常好。

    1. createRawCall 抛出的异常

      try {
          call = rawCall = createRawCall();
      } catch (Throwable t) {
          failure = creationFailure = t;
      }
      

      如果出异常,直接回调,不执行接下来 enqueue 方法。

    2. 执行 okhttp3.Call#enqueueokhttp3.Callback 抛出的网络请求异常

    3. 网络请求成功后在 okhttp3.Callback#onResponseparseResponse 时抛出的异常

      try {
          response = parseResponse(rawResponse);
      } catch (Throwable e) {
          callFailure(e);
          return;
      }
      

    5. CallAdapter

    前面已经简单介绍过 ServiceMethod#createCallAdapter,它会从 adapterFactories 中找到第一个符合条件的 CallAdapter.Factory

    5.1 retrofit-adapters

    先来看 Retrofit 提供的 retrofit-adapters 模块,目前供我们选择使用的有 guavajava8rxjava,分别对应的 CallAdapter.FactoryGuavaCallAdapterFactoryJava8CallAdapterFactoryRxJavaCallAdapterFactory

    Retrofit#build 时,除了我们自己添加的 CallAdapter.Factory, 还会添加两个默认的 CallAdapter.FactoryExecutorCallAdapterFactoryDefaultCallAdapterFactory

    // Make a defensive copy of the adapters and add the default Call adapter.
    List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
    adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    

    Retrofit 源码中有大量类似 List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); 的例子,不直接使用成员变量,而是将成员变量重新拷贝给一个新的临时变量,这样虽然多申请了4个字节内存,但如果以后将成员变量改成入参,就可以不用改代码直接使用了,是一种好的编码习惯。

    5.2 default

    再看默认的 CallAdapter.Factory

    CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
        if (callbackExecutor != null) {
            return new ExecutorCallAdapterFactory(callbackExecutor);
        }
        return DefaultCallAdapterFactory.INSTANCE;
    }
    

    DefaultCallAdapterFactoryExecutorCallAdapterFactory 返回的类型都是 retrofit2.Call<R>

    DefaultCallAdapterFactory 中,CallAdapter#adapt 什么都不做,直接返回 retrofit2.Call<R>。而 ExecutorCallAdapterFactoryCallAdapter#adapt 则返回 ExecutorCallbackCall<T>,它实现了 retrofit2.Call<R>,会传入一个 Executor,同步调用不变,异步调用时会在指定的 Executor 上执行。

    5.3 adapt

    看下 CallAdapteradapt 方法

    /**
      * Returns an instance of {@code T} which delegates to {@code call}.
      */
    <R> T adapt(Call<R> call);
    

    它的作用就是把 retrofit2.Call<R> 转换成我们需要的 T

    CallAdapters ? extends CallAdapter.Factory T
    guava retrofit2.adapter.guava.GuavaCallAdapterFactory com.google.common.util.concurrent.ListenableFuture
    java8 retrofit2.adapter.java8.Java8CallAdapterFactory java.util.concurrent.CompletableFuture
    rxjava retrofit2.adapter.rxjava.RxJavaCallAdapterFactory rx.Observable
    default retrofit2.ExecutorCallAdapterFactory retrofit2.Call<R>
    default retrofit2.DefaultCallAdapterFactory retrofit2.Call<R>

    List<CallAdapter.Factory> 中添加的顺序是我们指定的一个或多个 CallAdapter.Factory,默认的 ExecutorCallAdapterFactoryDefaultCallAdapterFactory,查找时按顺序查找。

    6. Converter

    Converter 的作用就是将 HTTP 请求返回的数据格式转换成我们需要的对象,或将我们提供的对象转换成 HTTP 请求需要的数据格式。

    public interface Converter<F, T> {
        T convert(F value) throws IOException;
    }
    

    接口非常清晰,将 F 转换成 T

    6.1 Factory

    来看 Converter.Factory

    abstract class Factory {
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }
    
        public Converter<?, RequestBody> requestBodyConverter(Type type,
            Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            return null;
        }
    
        public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }
    }
    
    1. responseBodyConverter 用于将 HTTP 请求返回的 response 转换成我们指定的类型。
    2. requestBodyConverter 用于将 BodyPartPartMap 3种类型的参数转换成 HTTP 的请求体。
    3. stringConverter 用于将 FieldFieldMapHeaderPathQueryQueryMap 这几种类型的参数转换成 String

    6.2 retrofit-converters

    CallAdapter 类似,Retrofit 也提供了默认的 Converter.Factory——BuiltInConverters,只能处理基本的 ResponseBodyRequestBodyString 类型。

    在 Retrofit 提供的 retrofit-converters 模块,供我们选择的有 GsonJacksonMoshiProtocol BuffersXMLScalarWire,我们常用的有 GsonConverterFactory

    需要注意的是,Jake Wharton 在他的一篇演讲 Simple HTTP with Retrofit 2 中说道

    I want to stress that the order matters. This is the order in which we’re going to ask each one whether or not it can handle a type. What I have written above is actually wrong. If we ever specify a proto, it’s going to be encoded as JSON, which will try and deserialize the response buddy as JSON. That’s obviously not what we want. We will have to flip these because we want to check protocol buffers first, and then JSON through GSON.

    说的就是 Retrofit.Builder#addConverterFactory 的顺序非常重要,先添加的 Converter.Factory 会先用来解析,而 Gson 非常强大,如果第一个添加 GsonConverterFactory,则其他想要转换的类型如 Protocol Buffers 就不会执行,因此建议将 GsonConverterFactory 作为最后一个添加

    7. 总结

    Retrofit 的源码还是很难的,反反复复看了很多遍,除了其原理和流程外,从中也学到了一些技巧和设计模式。在写这篇文章的同时又把思路和流程重新理了一遍,对自己帮助还是非常大的。关于源码最大的感受就是各个类之间传对象调用感觉非常乱,也增加了理解的难度,如 RetrofitServiceMethod 之间就互相依赖。

    本文是 慌不要慌 原创,发表于 https://danke77.github.io/,请阅读原文支持原创 https://danke77.github.io/2016/08/06/retrofit-source-analysis/,版权归作者所有,转载请注明出处。

    相关文章

      网友评论

      • 小草房Fang:java 还能在 ios上跑吗? 为什么要支持IOS?

      本文标题:Retrofit 源码分析

      本文链接:https://www.haomeiwen.com/subject/sfmdsttx.html