Skip to content

Retrofit源码解析

更新: 3/18/2026 字数: 0 字 时长: 0 分钟

基本使用

这里关于Retrofit的基本使用不多赘述了,包括结合rxjava,gson等等,这里给一个简单的demo:

kotlin
interface ApiService {

  @GET("getUserData")
  fun getUserData(): Call<ResponseBody>

}

fun main() {
  val retrofit = Retrofit.Builder()
    .baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
    .build()
  val service = retrofit.create(ApiService::class.java)
  val call: Call<ResponseBody> = service.getUserData()
  call.enqueue(object : Callback<ResponseBody> {
    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
      val userBean = response.body()?.string()
      println("userBean: $userBean")
    }

    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
      println("onFailure: $t")
    }
  })
}

源码分析

Retrofit.create()

看下代码:

java
public <T> T create(final Class<T> service) {
    // 校验接口的合法性
    validateServiceInterface(service);
    return (T)
    Proxy.newProxyInstance(
        service.getClassLoader(),
        new Class<?>[] {service},
        new InvocationHandler() {
            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) {
                    // 如果外部调用的是 Object 中声明的方法的话则直接调用
                    // 例如 toString()、hashCode() 等方法
                    return method.invoke(this, args);
                }
                // 空参数的处理,直接转成空数组
                args = args != null ? args : emptyArgs;
                Reflection reflection = Platform.reflection;
                // 根据 method 是否默认方法来决定如何调用
                return reflection.isDefaultMethod(method)
                ? reflection.invokeDefaultMethod(method, service, proxy, args)
                : loadServiceMethod(service, method).invoke(proxy, args);
            }
        });
}

这里的核心就是这里所实现的动态代理模式了,我们来详细看看:

java
return (T)
    Proxy.newProxyInstance(
        service.getClassLoader(),
        new Class<?>[] {service},
        new InvocationHandler() { ... });

这个是创建动态代理对象的标准写法,Proxy.newProxyInstance(...)有三个参数:

  1. 类加载器
java
service.getClassLoader()

用接口本身的类加载器来加载代理类。

比如 ApiService 是由哪个 ClassLoader 加载的,代理类就尽量用同一个。

  1. 代理要实现哪些接口

这里的意思是代理要实现哪些接口,这里就是service接口。如果 serviceApiService.class,那么返回的对象运行时就相当于:

java
class $Proxy0 implements ApiService

所以我们拿到的api的类型才是ApiService

  1. InvocationHandler

这里是最关键的地方,你对代理对象的任何方法调用,都会进到这里:

java
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
    throws Throwable

参数含义:

  • proxy:当前代理对象本身
  • method:你调用的哪个方法
  • args:调用方法时传入的参数

通过动态代理,Retrofit会将我们对ApiService的调用操作转发给InvocationHandler来完成。这样在后续会通过反射拿到我们在声明getUserData()时标注的各个配置项等信息,再将这些配置项拼接为Okhttp的一个网络请求。当调用call.enqueue时就会触发InvocationHandler去发起Okhttp网络请求。

Retrofit会根据method是否是默认方法来决定,如果是默认方法就调用接口自身的默认实现,否则就走loadServiceMethod(method)方法,看一下这个方法:

java
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();  

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. 将接口方法的method转为ServiceMethod对象,包含了接口方法的具体信息
  2. 因为单个接口方法可能会先后被调用许多次,所以放到serviceMethodCache中复用

ServiceMethod

ServiceMethod是个抽象类,他的直接子类只有一个HttpServiceMethod,这个类也是一个抽象类,其包含两个泛型声明,ResponseT 表示的是接口方法返回值的外层包装类型,ReturnT 表示的是我们实际需要的数据类型。例如,对于 fun getUserData(): Call<UserBean> 方法,ResponseT 对应的是 Call,ReturnT 对应的是 UserBean。

HttpServiceMethod实现了invoke方法,并将操作转交给了另一个抽象方法adapt来完成。可以看到,即使我们为接口方法声明的返回值类型是 Observable<UserBean>invoke 方法内部其实还是需要创建出一个 Call 对象的,HttpServiceMethod 只是把 Call 转换为 Observable 的这个过程交由了 adapt 方法来完成

java
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
 
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
    
  ···

}

再来看看HttpServiceMethod.parseAnnotations()方法:

java
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //是否是 Suspend 函数,即是否以 Kotlin 协程的方式来进行请求
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
        //省略 Kotlin 协程的一些处理逻辑
    } else {
      adapterType = method.getGenericReturnType();
    }
	
    //重点1
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
      
    //拿到包装类内部的具体类型,例如,Observable<UserBean> 内部的 UserBean
    //responseType 不能是 okhttp3.Response 或者是不包含具体泛型类型的 Response
    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<String>)");
    }
    // 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.");
    }
	
    //重点2
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      //重点3
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } 
    
    //省略 Kotlin 协程的一些处理逻辑
	···
        
  }

  ···
    
}

parseAnnotations 方法的主要逻辑是:

  1. 先通过createCallAdapter(retrofit, method, adapterType, annotations 方法拿到 CallAdapter 对象,CallAdapter 就用于实现接口方法的返回值包装类处理逻辑。例如,getUserData()方法的返回值包装类类型如果是 Call ,那么返回的 CallAdapter 对象就对应 DefaultCallAdapterFactory 包含的 Adapter;如果是 Observable,那么返回的就是 RxJava2CallAdapterFactory 包含的 Adapter
  2. 再通过 createResponseConverter(retrofit, method, responseType)方法拿到 Converter 对象,Converter 就用于实现接口方法的返回值处理逻辑。例如,getUserData()方法的目标返回值类型如果是 ResponseBody,那么 Converter 对象就对应 BuiltInConverters;如果是 UserBean,那么就对应 GsonConverterFactory
  3. 根据前两个步骤拿到的值,构造出一个 CallAdapted 对象并返回

再来看看这个CallAdapted对象:

java
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<ResponseT> call, Object[] args) {
        return callAdapter.adapt(call);
    }
}

这里的这个CallAdapted正式HttpServiceMethod的子类,在以上步骤中已经找到了可以实现将 Call 转换为 Observable 的 CallAdapter 了,所以对于 CallAdapted 来说,其 adapt 方法会直接将 Call 提交给 CallAdapter,由其去实现这种转换过程。

OkhttpCall

这是实际发起Okhttp请求的地方。当我们调用 fun getUserData(): Call<ResponseBody> 方法时,返回的 Call 对象实际上是 OkHttpCall 类型,而当我们调用 call.enqueue(Callback)方法时,enqueue 方法就会发起一个 OkHttp 请求,传入的 retrofit2.Callback 对象就会由 okhttp3.Callback本身收到回调时再进行中转调用。

java
final class OkHttpCall<T> implements Call<T> {
  private final RequestFactory requestFactory;
  private final Object[] args;
  private final okhttp3.Call.Factory callFactory;
  private final Converter<ResponseBody, T> responseConverter;

  private volatile boolean canceled;

  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;

  @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
  private @Nullable Throwable creationFailure;

  @GuardedBy("this")
  private boolean executed;
    
  @Override
  public void enqueue(final Callback<T> callback) { 
    ···
    okhttp3.Call call;
    ··· 
    call.enqueue( new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }

            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }

          @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) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }
 
   ···
    
}

总结

  • 首先,我们通过 retrofit.create(ApiService::class.java)得到一个 ApiService 的动态实现类,这是通过 Java 原生提供的Proxy.newProxyInstance 代表的动态代理功能来实现的。在拿到 ApiService 的实现类后,我们就可以直接调用 ApiService 中声明的所有方法了
  • 当我们调用了service.getUserData()方法时,Retrofit 会将每一个接口方法都抽象封装为一个 ServiceMethod 对象并缓存起来,我们的操作会转交给 ServiceMethod 来完成,由 ServiceMethod 来负责返回我们的目标类型,对应的是 serviceMethod.invoke(Object[] args)方法,args 代表的是我们调用接口方法时需要传递的参数,对应本例子就是一个空数组
  • ServiceMethod 使用到了工厂模式,由于网络请求最终的请求方式可能是多样化的,既可能是通过线程池来执行,也可能是通过 Kotlin 协程来执行,使用工厂模式的意义就在于可以将这种差异都隐藏在不同的 ServiceMethod 实现类中,而外部统一都是通过 parseAnnotations 方法来获取 ServiceMethod 的实现类
  • ServiceMethod 具有一个唯一的直接子类,即 HttpServiceMethod。HttpServiceMethod 自身已经找到了可以将 Call 转换为 Observable,ResponseBody 转换为 UserBean 的转换器,其invoke方法会构建出一个 OkHttpCall 对象,然后转发给抽象方法adapt,由adapt来发起实际的网络请求
  • 而不管外部的接口方法返回值类型是不是 Observable<UserBean>,最终的网络请求都是需要通过 OkHttpCall 来发起,HttpServiceMethod 依靠找到的转换器将 OkHttpCall 给隐藏在了内部

接口方法如何解析的

再来看看Retrofit是如何把interface内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求的。这个过程在 ServiceMethod 的 parseAnnotations 方法中就已经完成的了,对应的是 RequestFactory.parseAnnotations(retrofit, method)方法:

java
abstract class ServiceMethod<T> {
    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Class<?> service, Method method) {
        // 重点
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, service, 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);
    }

    abstract @Nullable T invoke(Object instance, Object[] args);
}

Retrofit是依靠Okhttp进行实际的网络请求,而Okhttp是通过构建一个Request对象来配置请求方式和请求参数,来发起网络请求的,所以Retrofit 也需要一个构建 Request 对象的过程,这个过程就隐藏在 RequestFactory 中。

RequestFactory采用了建造者模式,其 create(Object[] args)方法就会根据各项解析结果,最终返回一个 okhttp3.Request 对象:

java
final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

  private final Method method;
  private final HttpUrl baseUrl;
  final String httpMethod;
  private final @Nullable String relativeUrl;
  private final @Nullable Headers headers;
  private final @Nullable MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;
  final boolean isKotlinSuspendFunction;

  okhttp3.Request create(Object[] args) throws IOException {
    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args.length;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException(
          "Argument count ("
              + argumentCount
              + ") doesn't match expected count ("
              + handlers.length
              + ")");
    }

    RequestBuilder requestBuilder =
        new RequestBuilder(
            httpMethod,
            baseUrl,
            relativeUrl,
            headers,
            contentType,
            hasBody,
            isFormEncoded,
            isMultipart);

    if (isKotlinSuspendFunction) {
      // The Continuation is the last parameter and the handlers array contains null at that index.
      argumentCount--;
    }

    List<Object> argumentList = new ArrayList<>(argumentCount);
    for (int p = 0; p < argumentCount; p++) {
      argumentList.add(args[p]);
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
  }
    
}

OkHttpCall 是实际上发起网络请求的地方,所以最终 RequestFactory 的 create 方法会由 OkHttpCall 的 createRawCall() 方法来调用:

java
final class OkHttpCall<T> implements Call<T> {
     
  	private okhttp3.Call createRawCall() throws IOException {
    	okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    	if (call == null) {
      		throw new NullPointerException("Call.Factory returned null.");
    	}
    	return call;
  	}
     
}

ResponseBody映射为UserBean

OkHttp 默认的接口返回值对象是 ResponseBody,如果不引入converter-gson,我们只能将接口请求结果都定义为 ResponseBody,而不能是具体的 Bean 对象,因为 Retrofit 无法自动地完成 ResponseBody 到 UserBean 之间的转换操作,需要我们将这种转换规则告知 Retrofit。而这个规则也就是Converter接口,对应它的 responseBodyConverter方法:

//TODO