publicstaticvoidmain(String... args)throws IOException { // Create a very simple REST adapter which points the GitHub API. Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
// Create an instance of our GitHub API interface. GitHub github = retrofit.create(GitHub.class);
// Create a call instance for looking up Retrofit contributors. Call<List<Contributor>> call = github.contributors("square", "retrofit");
// Fetch and print a list of the contributors to the library. List<Contributor> contributors = call.execute().body(); for (Contributor contributor : contributors) { System.out.println(contributor.login + " (" + contributor.contributions + ")"); } } }
源码
创建Retrofit对象
创建Retrofit时,我们调用了new Retrofit.Builder()方法:
publicfinalclassRetrofit{ // ① privatefinal Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory; final HttpUrl baseUrl; final List<Converter.Factory> converterFactories; final List<CallAdapter.Factory> callAdapterFactories; final@Nullable Executor callbackExecutor; finalboolean validateEagerly;
// Do not add the default BuiltIntConverters and platform-aware converters added by build(). for (int i = 1, size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize(); i < size; i++) { converterFactories.add(retrofit.converterFactories.get(i)); }
// Do not add the default, platform-aware call adapters added by build(). for (int i = 0, size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize(); i < size; i++) { callAdapterFactories.add(retrofit.callAdapterFactories.get(i)); }
/** * The HTTP client used for requests. * <p> * This is a convenience method for calling {@link #callFactory}. */ public Builder client(OkHttpClient client){ return callFactory(Objects.requireNonNull(client, "client == null")); }
/** * Specify a custom call factory for creating {@link Call} instances. * <p> * Note: Calling {@link #client} automatically sets this value. */ public Builder callFactory(okhttp3.Call.Factory factory){ this.callFactory = Objects.requireNonNull(factory, "factory == null"); returnthis; }
/** * Set the API base URL. * * @see #baseUrl(HttpUrl) */ public Builder baseUrl(URL baseUrl){ Objects.requireNonNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl.toString())); }
/** * Set the API base URL. * * @see #baseUrl(HttpUrl) */ public Builder baseUrl(String baseUrl){ Objects.requireNonNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl)); }
/** * Set the API base URL. * <p> * The specified endpoint values (such as with {@link GET @GET}) are resolved against this * value using {@link HttpUrl#resolve(String)}. The behavior of this matches that of an * {@code <a href="">} link on a website resolving on the current URL. * <p> * <b>Base URLs should always end in {@code /}.</b> * <p> * A trailing {@code /} ensures that endpoints values which are relative paths will correctly * append themselves to a base which has path components. * <p> * <b>Correct:</b><br> * Base URL: http://example.com/api/<br> * Endpoint: foo/bar/<br> * Result: http://example.com/api/foo/bar/ * <p> * <b>Incorrect:</b><br> * Base URL: http://example.com/api<br> * Endpoint: foo/bar/<br> * Result: http://example.com/foo/bar/ * <p> * This method enforces that {@code baseUrl} has a trailing {@code /}. * <p> * <b>Endpoint values which contain a leading {@code /} are absolute.</b> * <p> * Absolute values retain only the host from {@code baseUrl} and ignore any specified path * components. * <p> * Base URL: http://example.com/api/<br> * Endpoint: /foo/bar/<br> * Result: http://example.com/foo/bar/ * <p> * Base URL: http://example.com/<br> * Endpoint: /foo/bar/<br> * Result: http://example.com/foo/bar/ * <p> * <b>Endpoint values may be a full URL.</b> * <p> * Values which have a host replace the host of {@code baseUrl} and values also with a scheme * replace the scheme of {@code baseUrl}. * <p> * Base URL: http://example.com/<br> * Endpoint: https://github.com/square/retrofit/<br> * Result: https://github.com/square/retrofit/ * <p> * Base URL: http://example.com<br> * Endpoint: //github.com/square/retrofit/<br> * Result: http://github.com/square/retrofit/ (note the scheme stays 'http') */ public Builder baseUrl(HttpUrl baseUrl){ Objects.requireNonNull(baseUrl, "baseUrl == null"); List<String> pathSegments = baseUrl.pathSegments(); if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { thrownew IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; returnthis; }
/** Add converter factory for serialization and deserialization of objects. */ public Builder addConverterFactory(Converter.Factory factory){ converterFactories.add(Objects.requireNonNull(factory, "factory == null")); returnthis; }
/** * Add a call adapter factory for supporting service method return types other than {@link * Call}. */ public Builder addCallAdapterFactory(CallAdapter.Factory factory){ callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null")); returnthis; }
/** * The executor on which {@link Callback} methods are invoked when returning {@link Call} from * your service method. * <p> * Note: {@code executor} is not used for {@linkplain #addCallAdapterFactory custom method * return types}. */ public Builder callbackExecutor(Executor executor){ this.callbackExecutor = Objects.requireNonNull(executor, "executor == null"); returnthis; }
/** Returns a modifiable list of call adapter factories. */ public List<CallAdapter.Factory> callAdapterFactories() { returnthis.callAdapterFactories; }
/** Returns a modifiable list of converter factories. */ public List<Converter.Factory> converterFactories() { returnthis.converterFactories; }
/** * When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate * the configuration of all methods in the supplied interface. */ public Builder validateEagerly(boolean validateEagerly){ this.validateEagerly = validateEagerly; returnthis; }
/** * 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) { thrownew IllegalStateException("Base URL required."); }
okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); }
// 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());
public static final class Builder { private final Platform platform; ... Builder(Retrofit retrofit) { platform = Platform.get(); } ... } class Platform { private static final Platform PLATFORM = findPlatform();
public final class Retrofit { ... public static final class Builder { private final List<Converter.Factory> converterFactories = new ArrayList<>(); ... public Builder addConverterFactory(Converter.Factory factory) { // 检查factory是否为null,然后加入到集合中 converterFactories.add(checkNotNull(factory, "factory == null")); return this; } ... public Retrofit build() { 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. // 首先添加BuiltInConverters converterFactories.add(new BuiltInConverters()); // 然后添加调用addConverterFactory方法传入的Converter.Factory的集合 converterFactories.addAll(this.converterFactories); // 最后添加platform默认的Converter.Factory集合 converterFactories.addAll(platform.defaultConverterFactories());
// 将API方法的返回类型从ResponseBody 转换为type final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> { private final Gson gson; private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { T result = adapter.read(jsonReader); if (jsonReader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); } return result; } finally { value.close(); } } }
// 将API方法的输入参数类型从 type转换为requestBody final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8"); private static final Charset UTF_8 = Charset.forName("UTF-8"); private final Gson gson; private final TypeAdapter<T> adapter;
final class Utils { ... 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."); } } ... } 复制代码
final class RequestFactory { static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } // method对象 private final Method method; // 基础url private final HttpUrl baseUrl; // 请求方法 final String httpMethod; // 相对url,它与基础url组成请求路径 private final @Nullable String relativeUrl; // 请求头 private final @Nullable Headers headers; // 表示具体请求中的媒体类型信息 private final @Nullable MediaType contentType; // 是否有请求体 private final boolean hasBody; // 是否是Form表单提交 private final boolean isFormEncoded; // 是否支持文件上传的Form表单 private final boolean isMultipart; // private final ParameterHandler<?>[] parameterHandlers; // 是否是kotlin挂起函数 final boolean isKotlinSuspendFunction; /** * Inspects the annotations on an interface method to construct a reusable service method. This * requires potentially-expensive reflection so it is best to build each service method only once * and reuse it. Builders cannot be reused. */ // 检查接口方法上的注释以构造可重用的服务方法。这需要潜在的昂贵反射,因此最好只构建一次每个服务方法并重用它。 // 构建器不能重用。 static final class Builder { private static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*"; private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM); // 传入的retrofit对象 final Retrofit retrofit; // 传入的method对象 final Method method; // method对象中的注解 final Annotation[] methodAnnotations; // method中参数注解数组 final Annotation[][] parameterAnnotationsArray; // method中参数类型数组 final Type[] parameterTypes; boolean gotField; boolean gotPart; boolean gotBody; boolean gotPath; boolean gotQuery; boolean gotQueryName; boolean gotQueryMap; boolean gotUrl; @Nullable String httpMethod; boolean hasBody; boolean isFormEncoded; boolean isMultipart; @Nullable String relativeUrl; @Nullable Headers headers; @Nullable MediaType contentType; @Nullable Set<String> relativeUrlParamNames; @Nullable ParameterHandler<?>[] parameterHandlers; boolean isKotlinSuspendFunction; Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; // 获取方法注解 this.methodAnnotations = method.getAnnotations(); // 获取方法参数类型 this.parameterTypes = method.getGenericParameterTypes(); // 获取方法注解数组 this.parameterAnnotationsArray = method.getParameterAnnotations(); } RequestFactory build() { // 遍历注解,对注解进行解析 for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); }
if (httpMethod == null) { throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.)."); }
if (!hasBody) { if (isMultipart) { throw methodError(method, "Multipart can only be specified on HTTP methods with request body (e.g., @POST)."); } if (isFormEncoded) { throw methodError(method, "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, lastParameter = parameterCount - 1; p < parameterCount; p++) { parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); }
if (relativeUrl == null && !gotUrl) { throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError(method, "Non-body HTTP method cannot contain @Body."); } if (isFormEncoded && !gotField) { throw methodError(method, "Form-encoded method must contain at least one @Field."); } if (isMultipart && !gotPart) { throw methodError(method, "Multipart method must contain at least one @Part."); } // 返回一个RequestFactory对象 return new RequestFactory(this); } // 对注解进行解析 private void parseMethodAnnotation(Annotation annotation) { // 判断解析类型,根据注解的类型进行相应的解析 if (annotation instanceof DELETE) { parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false); } else if (annotation instanceof GET) { parseHttpMethodAndPath("GET", ((GET) annotation).value(), false); } else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } else if (annotation instanceof POST) { parseHttpMethodAndPath("POST", ((POST) annotation).value(), true); } else if (annotation instanceof PUT) { parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof retrofit2.http.Headers) { String[] headersToParse = ((retrofit2.http.Headers) annotation).value(); if (headersToParse.length == 0) { throw methodError(method, "@Headers annotation is empty."); } headers = parseHeaders(headersToParse); } else if (annotation instanceof Multipart) { if (isFormEncoded) { throw methodError(method, "Only one encoding annotation is allowed."); } isMultipart = true; } else if (annotation instanceof FormUrlEncoded) { if (isMultipart) { throw methodError(method, "Only one encoding annotation is allowed."); } isFormEncoded = true; } } //解析Http请求方法和路径 private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { ... } // 解析请求头 private Headers parseHeaders(String[] headers) { ... } ... } ... } 复制代码
/** Adapts an invocation of an interface method into an HTTP call. */ // 将接口方法的调用调整为HTTP请求 abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> { /** * Inspects the annotations on an interface method to construct a reusable service method that * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service * method only once and reuse it. */ // 检查接口方法上的注释,以构造一个可重用的服务方法,该服务方法表示HTTP。 // 这需要潜在的昂贵反射,因此最好只构建一次每个服务方法并重用它。 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; // 是否是kotlin挂起函数 if (isKotlinSuspendFunction) { ... } else { // 获取方法返回类型 adapterType = method.getGenericReturnType(); } // 1、获取CallAdapter对象 // 根据之前的分析,这里获得的是DefaultCallAdapterFactory CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); // 校验返回类型是否正确 Type responseType = callAdapter.responseType(); // 返回类型不能为okhttp3.Response类型 if (responseType == okhttp3.Response.class) { throw methodError(method, "'" + getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } // 返回类型不能是Response,必须要包含泛型才行,类似于Response<String> 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对象 // 由于我们设置了GsonConverterFactory,所以这里获得的是GsonConverterFactory对象 Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); // 获取一个okhttp3.Call.Factory对象,其实就是一个OkHttpClient对象 okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { ... } else { ... } }
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) { try { // 4、从retrofit中根据returnType和annotations获取CallAdapter return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create call adapter for %s", returnType); } } private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter( Retrofit retrofit, Method method, Type responseType) { Annotation[] annotations = method.getAnnotations(); try { // 5、从retrofit中根据responseType和annotations获取Converter return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create converter for %s", responseType); } } }
public final class Retrofit { ... // 创建CallAdapter对象 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { // 调用nextCallAdapter传入skipPast、returnType、annotations // 注意:这里传入的skipPast为null return nextCallAdapter(null, returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { // 检查一下returnType和annotations是否为null checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); // 这里找到callAdapterFactories集合的起始位置 // 由于skipPast为null所以获得的index为-1,然后加上1,起始位置还是0 // 开始遍历集合 int start = callAdapterFactories.indexOf(skipPast) + 1; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { // 我们在分析CallAdapter.Factory时知道,调用get方法表示了, // 判断returnType是否是该CallAdapter.Factory支持的类型 // 如果不支持将会返回null // 反之会返回对应的CallAdapter.Factory // 由于没有额外设置,所以这里返回的是DefaultCallAdapterFactory CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); // 如果有直接返回 if (adapter != null) { return adapter; } } // 到这里说明没有对应的CallAdapter.Factory // 拼接错误信息 StringBuilder builder = new StringBuilder("Could not locate call adapter for ") .append(returnType) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = callAdapterFactories.size(); i < count; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } // 抛出异常 throw new IllegalArgumentException(builder.toString()); } ... // 创建Converter对象 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) { // 调用nextResponseBodyConverter传入skipPast、returnType、annotations // 注意:这里传入的skipPast为null return nextResponseBodyConverter(null, type, annotations); } public <T> Converter<ResponseBody, T> nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { // 检查一下returnType和annotations是否为null checkNotNull(type, "type == null"); checkNotNull(annotations, "annotations == null"); // 这里找到converterFactories集合的起始位置 // 由于skipPast为null所以获得的index为-1,然后加上1,起始位置还是0 // 开始遍历集合 int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { // 我们在分析Converter.Factory时知道,调用responseBodyConverter方法表示了, // 判断能否将API方法的返回类型从ResponseBody 转换为type // 如果不能直接返回null, // 返回对应的Converter.Factory对象,我们之前设置的是GsonConverterFactory,所以这里返回的是GsonConverterFactory Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { // 如果有直接返回 return (Converter<ResponseBody, T>) converter; } }
// 到这里说明没有对应的Converter.Factory // 拼接错误信息 StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ") .append(type) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(converterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = converterFactories.size(); i < count; i++) { builder.append("\n * ").append(converterFactories.get(i).getClass().getName()); } // 抛出异常 throw new IllegalArgumentException(builder.toString()); } ... } 复制代码
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory { @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) {