retrofit源码阅读记录 - Xiasm/Java-Android-Learn GitHub Wiki

前言

retrofit源码没有多少,并且它的网络请求实现是用的okhttp,所以大体上的感觉就是它是在okhttp的基础上封装了一层,封装了什么呢?下面我们就来看一下它的源码吧!retrofit用到了动态代理和okhttp,关于这两个东西本文不再讲述,如果不知道的可以查些资料。

分析入口

先来看下Retrofit使用方式:

public interface Api {

    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId);

}

//标注1
Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BuildConfig.baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(HttpSettings.commonOkHttpClient())
                    .build();
//标注2
Api api = retrofit.create(Api.class);

api.groupList(1).enqueue(callback);

标注1处代码就是通过构建者模式获取一个Retrofit实例,没有什么可说的。直接看标注2处,通过retrofit实例的create方法拿到一个Api对象,调用api的方法就可以请求并处理结果了。
直觉上,你是不是感觉到了什么?Api就是一个接口,为什么拿到这个接口的实例就能调用它的方法了呢?所以呢。肯定有一个代理对象偷偷对这个方法所了些东西。好了,奥妙就在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);
        }
      });
}

看到这个方法,你是否明白了?对,retrofit内部就是用的动态代理去实现了Api里方法调用的处理。直接看InvocationHandler的实现:

private final Platform platform = Platform.get();

上面这句代码就是得到一个平台相关的东西,看内部实现:

private static final Platform PLATFORM = findPlatform();

static Platform get() {
  return PLATFORM;
}

private static Platform findPlatform() {
  try {
    //标注1
    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();
}

可以看出,对于我们Android来说获取Platform肯定是走到标注1处了。我们来看看这个Android是干嘛的?

static class Android extends Platform {
  @Override public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }

  @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    return new ExecutorCallAdapterFactory(callbackExecutor);
  }

  //标注1
  static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override public void execute(Runnable r) {
      handler.post(r);
    }
  }
}

接着看标注1,MainThreadExecutor内部维护了一个Handler,这个handler拿的是主线程的looper,所以大概能猜出来这个platform就是用来将要执行的东西切换到主线程的。用过okhttp的同学肯定知道,okhttp的网络请求回调是在工作线程,就是线程池里的线程,所以我们用okhttp的时候一般会将子线程的回调切换到主线程然后执行更新ui的操作。所以这个platform的职责就是将子线程的回调切换到主线程。看完了Platform,接着看InvocationHandler中invoke方法的实现:

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

我们知道,动态代理中调用被代理对象的方法实现就是这个invoke了,首先第一个if判断肯定不满足,第二个if判断的返回值对Android来说默认的就是false,直接往下看:

ServiceMethod serviceMethod = loadServiceMethod(method);

这个method就是我们要代理的method,在这里肯定就是下面方法了:

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);

进入loadServiceMethod(method)内部:

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就是一个方法的缓存,因为我们的Api的方法可能不止调用一次,所以对他的方法做了缓存,所以我们直接看这一行 result = new ServiceMethod.Builder(this, method).build();通过构建者模式创建了一个ServiceMethod,那么ServiceMethod是什么呢?看源码:

final class ServiceMethod<T> {

  //...

  static final class Builder<T> {
    public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      //标注1
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

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

      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).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }    
  }

}

可以看出,Builder内部将method的注解、参数等等解析好然后创建出ServiceMethod,所以一个ServiceMethod里面就存储了请求接口的url、参数等等有用的信息,有一个地方需要我们注意,就是bulid()方法内部的标注1处:创建了一个CallAdapter,我们看createCallAdapter()方法:

private CallAdapter<?> createCallAdapter() {
  Type returnType = method.getGenericReturnType();
  if (Utils.hasUnresolvableType(returnType)) {
    throw methodError(
        "Method return type must not include a type variable or wildcard: %s", returnType);
  }
  if (returnType == void.class) {
    throw methodError("Service methods cannot return void.");
  }
  Annotation[] annotations = method.getAnnotations();
  try {
    return retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(e, "Unable to create call adapter for %s", returnType);
  }
}

public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}

public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
    Annotation[] annotations) {
  checkNotNull(returnType, "returnType == null");
  checkNotNull(annotations, "annotations == null");

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

  //...
  throw new IllegalArgumentException(builder.toString());
}

createCallAdapter()方法内部将method的注解和返回值类型拿到之后,调用了Retrofit的callAdapter,最终调用到Retrofit的nextCallAdapter方法,nextCallAdapter()方法会从adapterFactories里面去寻找callAdapter,如果没找到,最后会抛出异常。所以这个adapterFactories肯定是在api的方法调用钱就初始化好了,不然肯定抛异常,我们看下它在哪里初始化的:

Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
    List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
    Executor callbackExecutor, boolean validateEagerly) {
  this.callFactory = callFactory;
  this.baseUrl = baseUrl;
  this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
  this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
  this.callbackExecutor = callbackExecutor;
  this.validateEagerly = validateEagerly;
}

在Retrofit的构造方法里传过来的,大家还记得上面Retrofit是通过Builder创建的,我们看一下Retrofit.Builder的build()方法:

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

  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();
  }
  //标注1
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }

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

  // Make a defensive copy of the converters.
  List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

  return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
      callbackExecutor, validateEagerly);
}

这个build()方法里可谓是Retrofit实例创建大揭秘,看标注2处就是adapterFactories创建,并且默认加入了一个platform的callAdapter,这个platform是怎么来的呢?看标注1,这里判断callbackExecutor为空就创建一个平台默认的callbackExecutor,我们上面看了Platform的源码,在Platform类加载的时候就会调用findPlatform()方法,最后是创建了一个Android类,这个Android是继承自Platform的,所以标注1处如果我们在创建Retrofit的时候没有指定callbackExecutor,就会默认创建一个Android platform,则我们的callbackExecutor和callAdapterFactory就是下面这俩:

static class Android extends Platform {
  @Override public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }

  @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    return new ExecutorCallAdapterFactory(callbackExecutor);
  }

  static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override public void execute(Runnable r) {
      handler.post(r);
    }
  }
}

到这里我们明白了callAdapter是如何创建的,也将Platform和Retrofit联系起来了,我们重新回到Retrofit的create()方法的InvocationHandler里

@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);
  }
  //标注1
  ServiceMethod serviceMethod = loadServiceMethod(method);
  //标注2
  OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
  return serviceMethod.callAdapter.adapt(okHttpCall);
}
});

看标注1,现在我们创建了ServiceMethod,到这里你已经知道这个ServiceMethod的大致职责了吧,它就是保存了method的一些信息等,然后看标注2,创建了一个OkHttpCall,这个OkHttpCall内部封装了okhttp请求相关的东西,然后将serviceMethod的callAdapter和okhttpCall关联了起来。我们已经知道serviceMethod的callAdapter就是Android的defaultCallAdapterFactory(),也就是ExecutorCallAdapterFactory。好了,我们先不管ExecutorCallAdapterFactory,到这里我们先来理一下思路,首先通过Retrofit的create()方法,创建了一个动态代理的对象,代理的是Api,然后我们拿到这个api,调用api里面的方法,这个方法就会被代理,也就走到了create()方法内部的invoke()方法里面,执行代理方法。而我们在invoke里就是拿到api的method相关的注解参数等封装成serviceMethod,然后创建一个okhttp请求相关的OkHttpCall,将两者关联起来,最后调用serviceMethod.callAdapter.adapt(okHttpCall)并返回,所以最后 return serviceMethod.callAdapter.adapt(okHttpCall) 就是代理方法返回的结果。这个结果实际上就是我们Api的的方法的返回值:Call<List>。
这个返回值通过serviceMethod.callAdapter.adapt(okHttpCall)得到,我们已经知道callAdapter实际上就是ExecutorCallAdapterFactory,看它的adapt()方法:

@Override public <R> Call<R> adapt(Call<R> call) {
  return new ExecutorCallbackCall<>(callbackExecutor, call);
}

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()) {
              // 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<T> call, final Throwable t) {
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            callback.onFailure(ExecutorCallbackCall.this, t);
          }
        });
      }
    });
  }

  @Override public boolean isExecuted() {
    return delegate.isExecuted();
  }

  @Override public Response<T> execute() throws IOException {
    return delegate.execute();
  }

  @Override public void cancel() {
    delegate.cancel();
  }

  @Override public boolean isCanceled() {
    return delegate.isCanceled();
  }

  @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
  @Override public Call<T> clone() {
    return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
  }

  @Override public Request request() {
    return delegate.request();
  }
}

最终的ExecutorCallbackCall通过构造方法传入OkHttpCall,将所有的网络请求都交给OkHttpCall处理。

⚠️ **GitHub.com Fallback** ⚠️