Retrofit 2.6.2源码分析,从小白视角让你不止会用

8,134 阅读9分钟

全程代码高能预警,为了让读者看的明白,本文是从一个没有读过源码的小白视角来分析Retrofit的,代码量非常大,阅读时如有不适,及时休息。

简单流程图

Retrofit简单使用

对于Retrofit相信大家都不会陌生,使用起来也非常简单,以下代码就可以简单使用:

   val retrofit = Retrofit.Builder()
            .baseUrl("https://www.github.com")
            .build()

        val userService = retrofit.create(UserService::class.java)
        val call = userService.getUserInfo("1")
        call.enqueue(object : Callback<ResponseBody> {
            override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
            }

            override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
            }
        })

用法都会,但是这几段代码究竟做了什么呢?接下来我会从源码的角度来分析一遍。

Retrofit源码分析

以下是retrofit的create方法:

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  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();
          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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

第一行主要是对传入的class进行校验,具体校验方法如下:

static <T> void validateServiceInterface(Class<T> service) {
  if (!service.isInterface()) {
    throw new IllegalArgumentException("API declarations must be interfaces.");
  }
  // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
  // Android (http://b.android.com/58753) but it forces composition of API declarations which is
  // the recommended pattern.
  if (service.getInterfaces().length > 0) {
    throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
  }
}

看代码我们会发现,主要是从两个角度校验的,第一是class是不是一个接口,第二这个接口有没有继承自其他接口,那为什么会做这样的校验呢,我们后面再说。 而

  if (validateEagerly) {
    eagerlyValidateMethods(service);
  }

主要是为了程序的稳定性,这里我们就不多说了,主要看下面。细心的读者已经发现了

Proxy.newProxyInstance

从这我们可以看出create方法里面主要是使用了动态代理的方式,那么回到刚才第一段代码的校验我们就很容易理解了。而动态代理里面又做了什么呢?

// If the method is a method from Object then defer to normal invocation.
  if (method.getDeclaringClass() == Object.class) {
            return method.invoke(this, args);
  }

这段代码组要是看方法是不是Object里面的,如果是我们就不处理。

if (platform.isDefaultMethod(method)) {
      return platform.invokeDefaultMethod(method, service, proxy, args);
      }

这段代码主要是适配平台的,我们可以简单看一下这个Platform,

  private static final Platform PLATFORM = findPlatform();

static Platform get() {
  return PLATFORM;
}

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) {
  }
  return new Platform();
}

重点是下面这段代码

return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

这段代码我们可以分两部分解读,首先是loadServiceMethod(method),它主要是做什么的呢,让我们跟进去看一下

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

从上面代码中不难看出主要是返回一个ServiceMethod,会先从serviceMethodCache中查看有没有缓存,有的话直接返回,没有则创建一个并加入缓存,创建时则会先调用下parseAnnotations方法。ServiceMethod是一个抽象类,里面主要有两个方法,

 static <T> ServiceMethod<T> 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);
}

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

看ServiceMethod的parseAnnotations方法会发现最终返回的是HttpServiceMethod.parseAnnotations,打开HttpServiceMethod我们会发现它是ServiceMethod方法的一个实现类,让我们看看parseAnnotations究竟做了什么,代码稍微有点长,我就隐藏了下kotlin协程相关方面的处理(这段代码只有用到协程时才会调用)

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) {
    ......
  } else {
    adapterType = method.getGenericReturnType();
  }

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

  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);

  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  if (!isKotlinSuspendFunction) {
    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<ResponseT>>) callAdapter);
  } else {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
        callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
        continuationBodyNullable);
  }
}

分析代码我们会发现中间会创建一个callAdapter和一个responseConverter,最终调用

return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

首先我们先来看callAdapter,通过跟踪代码发现最终走到Retrofit的

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

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

最后从callAdapterFactories中取到,那么callAdapterFactories是什么又是怎么存进去的呢,最终跟踪到了Retrofit的Build方法中:

 /**
   * Create the {@link Retrofit} instance using the configured values.
   * <p>
   * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
   * OkHttpClient} will be created and used.
   */
  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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

    // Make a defensive copy of the converters.
    List<Converter.Factory> 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);
  }

从这里不难看出如果创建Retrofit的时候没有添加一个的话最终会添加一个默认的

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

在这里重点提一下callbackExecutor,这个由Platform创建的运行在android环境中最终会返回一个MainThreadExecutor,下面是具体代码

 @Override public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }
  
  static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

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

而MainThreadExecutor中有个handler,会传入Looper.getMainLooper(),最终就是通过handler来最终于android主线程进行通讯的。回到前面DefaultCallAdapterFactory,发现里面有个get方法,我们的callAdapter最终就是通过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<Foo> 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<Object, Call<?>>() {
    @Override public Type responseType() {
      return responseType;
    }

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

而responseConverte也是最终能追踪到Retrofit的Build()中,下面我们继续看HttpServiceMethod的parseAnnotations的最终调用,

return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

最终会返回一个CallAdapted对象,CallAdapted则是继承自HttpServiceMethod,走到这Retrofit的create方法最终执行的前半部分就分析完了,感觉好累😫,喝口茶我们继续分析下半段invoke,

loadServiceMethod(method).invoke(args != null ? args : emptyArgs)

通过前面的分析我们知道invoke最终会走到HttpServiceMethod中的invoke,里面具体做了什么呢,先看代码

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

我们发现首先创建了一个OkHttpCall,然后调用了adapt方法,adapt方法则是HttpServiceMethod中的一个抽象类

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

看到这里似乎又进了死胡同,别着急前面分析代码中知道有一个CallAdapted是HttpServiceMethod的实现类,而最终adapt方法则是进入了CallAdapted的adapt方法中

 @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
     return callAdapter.adapt(call);
   }

最终则会调用callAdapter.adapt(call),而callAdapter则是前面loadServiceMethod中创建的,bingo一切都对上了。

 @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<Foo> 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<Object, Call<?>>() {
     @Override public Type responseType() {
       return responseType;
     }

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

通过上面的CallAdapter创建代码发现最终返回了一个ExecutorCallbackCall,那么ExecutorCallbackCall又是什么呢?继续看代码

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) {
     checkNotNull(callback, "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();
   }
 }

在这里会发现几个熟悉的方法enqueue、execute,看到这里相信大家都恍然大悟了,当我们在使用过程中

  val call = userService.getUserInfo("1")
       call.enqueue(object : Callback<ResponseBody> {
           override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
           }

           override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
           }
       })

调用的enqueue方法就是这里面的enqueue方法,callbackExecutor就是Retrofit build时传入的MainThreadExecutor,callback则是前面HttpServiceMethod的invoke方法中的OkhttpCallback,ExecutorCallbackCall中的enqueue和execute方法则最终会调用delegate中的相关方法,delegate则是一个OkhttpCall对象,下面来看下OkhttpCall中的enqueue

@Override public void enqueue(final Callback<T> callback) {
   checkNotNull(callback, "callback == null");

   okhttp3.Call call;
   Throwable failure;

   ...省略若干...

   if (failure != null) {
     callback.onFailure(this, failure);
     return;
   }

   if (canceled) {
     call.cancel();
   }

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

从这里面不难看出最终是调用的OKhttp中的网络连接方法,最终走到下面的方法中

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();
   if (code < 200 || code >= 300) {
     try {
       // Buffer the entire body to avoid future I/O.
       ResponseBody bufferedBody = Utils.buffer(rawBody);
       return Response.error(bufferedBody, rawResponse);
     } finally {
       rawBody.close();
     }
   }

   if (code == 204 || code == 205) {
     rawBody.close();
     return Response.success(null, rawResponse);
   }

   ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
   try {
     T body = responseConverter.convert(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;
   }
 }

通过callback的回调使得我们拿到最终的结果,通过半天的追踪相信大家虽然会有点懵,但最终对Retrofit是如何运行的也有了一定的了解。

PS:喜欢的同学可以扫码关注我的公众号呦