前言

使用

依赖
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
创建Retrofit并请求数据
public final class SimpleService {
public static final String API_URL = "https://api.github.com";

public static class Contributor {
public final String login;
public final int contributions;

public Contributor(String login, int contributions) {
this.login = login;
this.contributions = contributions;
}
}

public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}

public static void main(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()方法:

public final class Retrofit {
// ①
private final 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;
final boolean validateEagerly;

Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}

...省略代码专用...

/**
* Build a new {@link Retrofit}.
* <p>
* Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods
* are optional.
*/
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;

Builder(Platform platform) {
this.platform = platform;
}

public Builder() {
// ②
this(Platform.get());
}

Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;

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

callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}

/**
* 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");
return this;
}

/**
* 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))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}

/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}

/**
* 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"));
return this;
}

/**
* 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");
return this;
}

/** Returns a modifiable list of call adapter factories. */
public List<CallAdapter.Factory> callAdapterFactories() {
return this.callAdapterFactories;
}

/** Returns a modifiable list of converter factories. */
public List<Converter.Factory> converterFactories() {
return this.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;
return this;
}

/**
* 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.Builder对象运用Builder设计模式链式调用为Retrofit.Builder中的属性进行赋值,调用build方法时,将这些属性赋值给一个Retrofit对象,最后将这个Retrofit对象返回。我们看一下这里面的属性都是什么意思。

在介绍各个属性之前先介绍一下

serviceMethodCache集合

在Retrofit类的内部会首先创建一个集合:

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

这个集合的Key是一个Mehtod对象,Value是与Key相对应的ServiceMethod对象。ServiceMethod对象是根据Method解析之后获得,这里面包含了Method的方法注解、参数注解等一些列属性。我们从集合的名字就能看出来,这里面是将Method和对应ServiceMethod进行缓存的集合,这种方法我们在EventBus源码解析的时候就遇到过。这样做的目的就是为了加快运行速度,我们在今后的开发中也能加以借鉴并运用。有关MethodServiceMethod都会在下文中进行讲解,这里如果不知道是什么意思也没关系。

Platform平台信息

这个对象是Retrofit.Builder对象中进行定义的。

  public static final class Builder {
private final Platform platform;
...
Builder(Retrofit retrofit) {
platform = Platform.get();
}
...
}

class Platform {
private static final Platform PLATFORM = findPlatform();

static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
// 如果是Android平台
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
// 如果是Java平台
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
...
}
复制代码

在这里我们可以看到这里会根据不同的平台信息返回对应的Platform对象,分别是AndroidJava8,重点分析一下Android

  static class Android extends Platform {
// 1、判断方法是否是默认方法,所谓默认方法是指是否是Object类中已经定义的方法
// 如果是就返回true,否则返回false
@IgnoreJRERequirement // Guarded by API check.
@Override boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}

@Override public Executor defaultCallbackExecutor() {
// 2、获取一个Executor对象,这个对象代表了回调执行器
return new MainThreadExecutor();
}

// 3、获得Android版本下默认的网络适配器集合
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
// 默认的请求适配器
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
// 如果Android系统版本大于24,则会返回一个CompletableFutureCallAdapterFactory和DefaultCallAdapterFactory组成的集合。
// 否则返回只有DefaultCallAdapterFactory对象的集合
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}

@Override int defaultCallAdapterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
}

// 4、获取Android版本下默认的转换器集合
@Override List<? extends Converter.Factory> defaultConverterFactories() {
// 如果Android系统版本大于24,则会返回只有CompletableFutureCallAdapterFactory对象的集合
// 否则返回一个长度为0的集合
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}

@Override int defaultConverterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
}

// 2.1 这里返回的是Android主线程的回调
// 也就是说当网络请求完成后会回调到Android主线程中去,这也是Retrofit和OkHttp的不同点之一
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
复制代码

Android平台里面我们关注四点:

1、判断传入的Method对象是否是默认方法
2、获取执行回调器,这里默认的是将网络请求结果回调到Android主线程中。
3、获得Android版本下默认的网络适配器集合,这里会根据Android版本号进行返回。
4、获取Android版本下默认的转换器集合,它也是会根据Android版本号进行返回。

这里有必要跟大家提前说一下,有关请求适配器(CallAdapter.Factory)和转换器(Converter.Factory)会在下面的文章中给出,这里先留一个印象。

callFactory对象

我们从单词的表面意思可以知道这个是请求工厂类,这个请求工厂类okhttp3Call类型,这也说明了Retrofit是基于okhttp进行封装的。定义callFactory对象我们可以调用Retrofit.Builder.callFactory方法进行设置,在Retrofit.Builder.build方法中会将这个对象赋值个Retrofit对象。

public final class Retrofit {
...
public static final class Builder {
private @Nullable okhttp3.Call.Factory callFactory;
...
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
...
public Retrofit build() {
...
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
...
}
}
...
}
复制代码

我们可以看到当我们没有调用Retrofit.Builder.callFactory方法时,会给我们默认设置一个OkHttpClient对象。

baseUrl基础请求路径

baseUrl作为请求的基础路径,它与我们在HTTP API接口中定义的方法注解中的相对路径组成了完整的请求路径。我们可以调用Retrofit.Builder.baseUrl方法进行设置,最后通过Retrofit.Builder.build方法中会将这个对象赋值个Retrofit对象。

public final class Retrofit {
...
public static final class Builder {
private @Nullable HttpUrl baseUrl;
...
// 传入URL
public Builder baseUrl(URL baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl.toString()));
}

// 传入String
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}

public Builder baseUrl(HttpUrl baseUrl) {
// 判空
checkNotNull(baseUrl, "baseUrl == null");
// 将url进行分割
List<String> pathSegments = baseUrl.pathSegments();
// 如果baseUrl不是以"/"结尾,抛出异常
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
...
public Retrofit build() {
...
// 再次判空
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
...
// 传入Retrofit对象中
return new Retrofit(..., baseUrl, ...,
..., ..., ...);
}
}
...
}
复制代码

设置的流程:

1、 可以调用两种方法,分别传入URLString
2、 对baseUrl进行判空,然后进行分割,如果是以"/"结尾会抛出异常。
3、 再进行一次判空,最后赋值给Retrofit对象。

converterFactories转换器集合

converterFactories集合内部存放的都是Converter.Factory对象,我们可以调用Retrofit.Builder.addConverterFactory方法进行添加。

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

// 根据converterFactories创建一个不可变集合传入
return new Retrofit(..., ..., unmodifiableList(converterFactories),
..., ..., ...);
}
}
...
}
复制代码

Converter.Factory从字面意思我们能猜出它是和转换有关,具体的探究会放到下文中。

callAdapterFactories请求适配器集合

callAdapterFactories集合中存放的是CallAdapter.Factory对象,调用Retrofit.Builder.addCallAdapterFactory方法来设置。

public final class Retrofit {
...
public static final class Builder {
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
...
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
...
public Retrofit build() {
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
// 这里不仅添加了调用addCallAdapterFactory方法时设置的CallAdapter.Factory对象
// 同时还添加了platform中默认的CallAdapter.Factory对象
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

// 根据callAdapterFactories创建一个不可变的集合传入
return new Retrofit(..., ..., ...,
unmodifiableList(callAdapterFactories), ..., ...);
}
}
...
}
复制代码

CallAdapter.Factory从字面意思可以看出是请求适配器,有关于请求适配器是什么,也会放到下文中进行探究。

callbackExecutor回调执行器

设置回调执行器我们可以通过Retrofit.Builder.callbackExecutor来设置,默认的会使用Platform的回调执行器,也就是会将请求的执行结果回调到Android主线程中。

public final class Retrofit {
...
public static final class Builder {
private @Nullable Executor callbackExecutor;
...
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
...
public Retrofit build() {
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 默认为platform中的回调执行器,会将请求结果回调到Android主线程
callbackExecutor = platform.defaultCallbackExecutor();
}
return new Retrofit(..., ..., ...,
..., callbackExecutor, ...);
}
}
...
}
复制代码

validateEagerly提前验证方法标识

这个标识表示是否需要提前验证HTTP API接口中的方法,我们通过调用Retrofit.Builder.validateEagerly方法进行设置,默认为false

public final class Retrofit {
...
public static final class Builder {
private boolean validateEagerly;
...
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
...
public Retrofit build() {
...
return new Retrofit(..., ..., ...,
..., ..., validateEagerly);
}
}
...
}
复制代码

到这里我们已经把Retrofit.Buidler中的属性分析完了,但是我们还遗留了两个问题:CallAdapter.FactoryConverter.Factory。这两个类到底是做什么的?这里来看一下。

CallAdapter.Factory

既然我们已经知道这个类是用来进行请求适配的,那么我们看一下里面是怎么运行的。

// 将响应类型为R的Call调整为T类型
public interface CallAdapter<R, T> {
// 返回此适配器将HTTP响应正文转换为Java时使用的值类型对象。
// 例如, Call <Repo>的响应类型是Repo。 这个类型用于准备传递给adapt的call。
Type responseType();
// 这个方法是将Call<R>对象转成代理类T
T adapt(Call<R> call);
//CallAdapter工厂,retrofit默认的DefaultCallAdapterFactory其中不对Call做处理,是直接返回Call。
abstract class Factory {
// 在这个方法中判断returnType是否是我们支持的类型,
// DefaultCallAdapterFactory没有做处理,因为在定义HTTP API接口中的方式时,returnType 即为Call<Requestbody>
// RxJavaCallAdapterFactory 就是判断returnType是不是Observable<?> 类型
// 不支持时返回null
// 返回值必须是Custom并且带有泛型(参数类型),根据HTTP API接口中的方法返回值,确定returnType
// 如: CustomCall<String> getCategories(),那确定returnType就是CustomCall<String>
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);

// 用于获取泛型的参数 如 Call<Requestbody> 中 Requestbody
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}

// 用于获取泛型的原始类型
// 如Call<Requestbody>拿到的原始类型就是Call
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
复制代码

看了这么多代码,可能还是有点云里雾里,我们找两个例子看一下。

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {

// 如果返回值不是Call类型返回空
// 也就是说我们在定义HTTP API接口中的方法时,返回值不是Call<?>类型的,将不会处理
if (getRawType(returnType) != Call.class) {
return null;
}

return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return ...;
}

@Override public Call<Object> adapt(Call<Object> call) {
return ...;
}
};
}
...
}
复制代码

我们经常会看到Retrofit + RxJava进行网络封装,如果要将RetrofitRxJava结合到一起就需要RxJavaCallAdapterFactory

public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
...
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
// 如果返回值不是Observable类型返回空
// 也就是说我们在定义HTTP API接口中的方法时,返回值不是Observable<?>类型的,将不会处理
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
...
}
}
复制代码

经过上面两个例子我们应该对CallAdapter.Factory有所了解了,这里来解释一下吧。

在我们定义HTTP API接口时,里面方法的返回值需要由Retrofit中添加的CallAdapter.Factory决定,如果定义了CallAdapter.Factory不支持的类型,请求将不会被执行。

Converter.Factory

从上面我们也知道Converter.Factory适用于转换的,我们看下源码,看看它到底是怎么转换的。

// 将F类型转成T类型
public interface Converter<F, T> {
@Nullable T convert(F value) throws IOException;
abstract class Factory {
// 判断能否将API方法的返回类型从ResponseBody 转换为type
// 如果不能直接返回null,反之返回对应的Converter.Factory对象
// type是由CallAdapter 接口里面的responseType()函数返回的。
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
// 将API方法的输入参数类型从 type转换为requestBody
// 用于转换被注解@Body, @Part 和 @PartMap标记的类型
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}

// 将API方法的输入参数类型从 type 转换为String
// 用于转换被注解 @Header, @HeaderMap, @Path, @Query 和 @QueryMap 标记的类型
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}

// 从type中提取index处泛型参数的上界
// 例如Map<String, ? extends Runnable>索引为1处返回Runnable
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}

// 从type中提取原始类类型
// 例如:List<? extends Runnable>返回的是List.class
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
复制代码

看完之后还是有点懵懵哒,我们还是找一个列子,还记的我们调用Retrofit.Builder.addConverterFactory传入的GsonConverterFactory吗,看一下。

// 这个Converter.Factory类使用Gson来解析Json
public final class GsonConverterFactory extends Converter.Factory {
// 使用默认的Gson对象来创建GsonConverterFactory
// 通过Gson将对象序列化或者反序列化成Json字符串
public static GsonConverterFactory create() {
return create(new Gson());
}

public static GsonConverterFactory create(Gson gson) {
// 检查传入的gson对象是否为空
// 如果为空直接抛出异常
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}

@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}

@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}

// 将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;

GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}

@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
复制代码

GsonRequestBodyConverter的例子中我们总结一下Converter.Factory的作用:

Converter.Factory是将HTTP API方法中的参数在requestBody和responseBody之间进行转换。

到这里我们才算真正的把Retrofit.Buidler中所涉及的属性和类分析完,休息一下,进行下半部分的分析。

img

调用Retrofit.create方法

public final class Retrofit {
...
public <T> T create(final Class<T> service) {
// 1、验证HTTP API接口
Utils.validateServiceInterface(service);
if (validateEagerly) {
// 2、验证HTTP API接口中的方法
eagerlyValidateMethods(service);
}
// 3、动态代理,整个Retrofit的核心之一
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 (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);
}
});
}
...
}
复制代码

上面这段代码中有给出了三处注释,我们逐个看一下

注释1:Utils.validateServiceInterface(Class service):

注释1中我们得知这个方法是对我们定义的HTTP API接口进行验证,看一下它是怎么验证的。

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.");
}
}
...
}
复制代码

这里做了两步验证:

1、验证传入的对象是否是一个接口,如果不是直接抛出异常。
2、如果是一个接口,看看这个接口是否是继接口,如果继承了,也会抛出异常。

注释2:eagerlyValidateMethods(Class<?> service)

    if (validateEagerly) {
eagerlyValidateMethods(service);
}
复制代码

这里是注释2处的代码,validateEagerly这个变量在之前的代码注释中已经给出了解释,它是对方法进行提前验证的标识,一般为false,但是我们还是需要看一下这个方法中是怎么进行验证的。

  private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
//获得接口中所有定义的方法,并遍历
for (Method method : service.getDeclaredMethods()) {
// 1、判断是否如果是default方法,Android平台返回false
// 2、判断方法是否是静态方法
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
// 如果符合条件,直接加载
loadServiceMethod(method);
}
}
}
复制代码

eagerlyValidateMethods方法中也是做了两件事:

1、找出接口中的所有方法,看看是否符合条件。
2、如果符合条件,直接加载方法。

public final class Retrofit {
//缓存集合,支持多线程访问、线程安全
//key:Method
//value:Method对应的ServiceMethod
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
...
ServiceMethod<?> loadServiceMethod(Method method) {
// 1、首先从方法缓存集合中获取
ServiceMethod<?> result = serviceMethodCache.get(method);
// 2、如果有,直接返回
if (result != null) return result;

synchronized (serviceMethodCache) {
// 3、在再次确认缓存中的是否有方法
result = serviceMethodCache.get(method);
if (result == null) {
// 4、对方法的注解进行解析
result = ServiceMethod.parseAnnotations(this, method);
// 5、将方法传到方法缓存集合中
serviceMethodCache.put(method, result);
}
}
return result;
}
}
复制代码

loadServiceMethod这里做了三步事情:

1、根据传入的Method从缓存集合中获取对应的ServiceMethod对象,如果有,直接返回;如果没有,对集合进行加锁,再次获取。这种方法将对象缓存起来的做法在分析EventBus源码的时候就见过,目的就是为了提高效率。
2、如果上一步中没有获取到ServiceMethod对象,将对Method进行解析。
3、将Method和它对应的ServiceMethod对象存入到缓存集合中,返回结果。

abstract class ServiceMethod<T> {
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);
}
复制代码

注释2处的验证HTTP API接口中的方法我们先分析到这里,上面这段代码我们先不进行探究,因为很快我们又会看到,具体流程会在接下来的分析中详细探究,希望大家对这个方法有所印象。我们先来总结一下注释2处都是做了哪些事情:

1、获取到HTTP API接口中所有方法,遍历加载这些方法。
2、加载的过程中先去缓存集合中看一下有没有与Method对应的ServiceMethod对象,如果有,直接返回;如果没有,对Method进行解析,将解析结果封装成一个ServiceMethod对象,并存入到缓存集合中,最后将ServiceMethod返回。

注释3: 动态代理

public final class Retrofit {
...
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
// 1、这里返回的是Android平台
private final Platform platform = Platform.get();
// 2、创建一个Object数组,长度为0
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// 3、如果该方法是来自Object的方法,则遵从正常调用。
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 4、在Android平台始终返回false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 5、加载方法
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
...
}
复制代码

当调用retrofit.create(ServiceApi.class)实际上会生成一个ServiceApi的代理类对象。从前面的基础知识准备中我们知道,当调用代理类对象中的方法时,最终会调用创建代理类对象所传入的第三个参数InvocationHandler.invoke方法回调中去,在这个回调中对方法进行处理。retrofit.create(ServiceApi.class)方法的主要流程已经在上面的代码注释中给出,这个方法最重要的一步是最后的加载方法,我们来看一下。

  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;
}
复制代码

嗯哼?上面这段代码是不是非常熟悉?没错,在之提前验证方法的过程中,我们已经见到过这个方法,方法中的流程这里就不再赘述,我们继续往下看。

abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1、根据传入的retrofit和method对象封装成RequestFactory
// 这一步主要是进行解析注解
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 2、获取方法的returnType
Type returnType = method.getGenericReturnType();
// 3、对方法的returnType进行验证
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.");
}
// 4、对方法的注解进行解析,并封装成一个ServiceMethod对象
// 这里返回的是HttpServiceMethod对象,他是ServiceMethod的子类
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

abstract @Nullable T invoke(Object[] args);
}
复制代码

哎呦,这个方法我们也见过,当时只是加深了一下印象,并没有对其进行探究。这个方法中做了四步操作,它们对应的操作已经在上面代码的注释中给出。我们重点来看一下第一步和第四步。

RequestFactory.parseAnnotations(retrofit, method)

这个方法主要是根据传入的retrofit对象和method对象封装成RequestFactory对象。

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) {
...
}
...
}
...
}
复制代码

这里没有把RequestFactory中所有的方法列出来,但是我们从上面的代码和注释中我们可以知道这个类都是做了哪些操作:

1、创建一个RequestFactory.Builder对象,同时传入Retrofit对象和Method对象。
2、创建完RequestFactory.Builder对象之后,会对Method对象的注解进行解析,解析的同时会对Buidler对象进行初始化。
3、最后通过build方法,创建一个RequestFactory对象,并进行初始化。

HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)

在得到RequestFactory对象之后,会调用HttpServiceMethod.parseAnnotations方法,将获取的RequestFactory传入,我们看一下这里面都是做了什么操作。

/** 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());
}
...
}
复制代码

这里由于代码过长,所以我们分步分析,在上面代码中有5处比较重要的注释,首先看一下注释1注释2,它们分别是用来获取CallAdapter.FactoryConverter.Factory,分别对应了注释4注释5处。注释4注释5都是从retrofit对象中获取,具体的操作需要看上段代码的下半部分,最终获取的是DefaultCallAdapterFactoryGsonConverterFactory,具体流程已经在注释中给出。
我们来看一下注释3处的操作,下面是注释3处的代码

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
...
// 获取一个okhttp3.Call.Factory对象,其实就是一个OkHttpClient对象
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 新建一个CallAdapted对象,传入requestFactory、callFactory、responseConverter、callAdapter
// 最后返回出去
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
...
} else {
...
}
}

...

HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}

@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
// 这里首先找的是子类的adapt方法
// 因为创建的是CallAdapted,所以会调用CallAdapted的adapt放方法
return adapt(call, args);
}

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

// CallAdapted继承自HttpServiceMethod
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;

// CallAdapted构造方法
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
// 调用父类的构造方法,也就是HttpServiceMethod的构造方法
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}

@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
// 返回callAdapter.adapt的结果
return callAdapter.adapt(call);
}
}
...
}
复制代码

这里我们需要把注释3处的过程捋一捋,由于这个过程跟之前的分析联系比较紧密,所以会有点绕:

1、新建一个CallAdapted对象,传入requestFactorycallFactoryresponseConvertercallAdapter
2、创建CallAdapted对象时调用其构造方法,由于它继承自HttpServiceMethod,又调用了HttpServiceMethod的构造方法,将参数传入。
3、我们在之前的动态代理最后一步会调用return loadServiceMethod(method).invoke(...)方法之后,又回调用HttpServiceMethod.adapt方法。这个方法在HttpServiceMethod中属于抽象方法,所以最终会调用其子类CallAdapted.adapt方法。
4、在CallAdapted.adapt的方法中会调用callAdapter.adapt方法,在分析CallAdapte.Factory时,我们知道这个方法是将Call对象转成代理类T。我们没有设置CallAdapte.Factory,所以使用的是DefaultCallAdapterFactory,所以又调用了DefaultCallAdapterFactory中的adapt方法,并将OkHttpCall传入了。

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
// 这个构造方法在Platform的Android子类中的defaultCallAdapterFactories方法中已经被调用。
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
//callbackExecutor为MainThreadExecutor,也就是说会将响应回调到Android主线程去
this.callbackExecutor = callbackExecutor;
}
//
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 如果不是Call类型不予处理
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);
// 查看注解是否包含SkipCallbackExecutor类型,我们在使用时并没有使用SkipCallbackExecutor的注解
// 所以这里的executor不为null
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) {
// 判断executor是否为空,如果为空返回Call,这个call属于OkHttpCall
// 如果不为空返回ExecutorCallbackCall
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
...
}
复制代码
static final class ExecutorCallbackCall<T> implements Call<T> {
...
}
复制代码

由于这里与之前的分析联系比较紧密,有些绕,一不小心就会被绕进去,所以还是分步分析。

1、在Platform的子类Android中,已经创建了DefaultCallAdapterFactory对象,并且传入了MainThreadExecutor,这保证了响应会被回调到Android主线程。
2、之前在获取CallAdapter类型的时候,已经调用了DefaultCallAdapterFactory.get方法,所以executor对象不为空,并且返回了一个匿名的CallAdapter对象。
3、在上面我们调用DefaultCallAdapterFactory.adapt方法时,就是调用了这个匿名对象的adapt方法,这里返回的是ExecutorCallbackCall对象。也就是说我们在做网络请求时就是使用这个ExecutorCallbackCall对象。

执行请求

我们在上面的分析中知道,其实是ExecutorCallbackCall对象进行网络请求,所以看一下它的源码。

同步请求

同步请求的方法我们也在之前的举例给出,我们看一下源码

  static final class ExecutorCallbackCall<T> implements Call<T> {

final Executor callbackExecutor;
final Call<T> delegate;

// 构造方法传入callbackExecutor、Call
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
// callbackExecutor属于MainThreadExecutor
this.callbackExecutor = callbackExecutor;
// delegate为OkHttpCall对象
this.delegate = delegate;
}
...
@Override public Response<T> execute() throws IOException {
// delegate其实就是OkHttpCall对象
return delegate.execute();
}
...
}
复制代码
final class OkHttpCall<T> implements Call<T> {
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;

synchronized (this) {
...
call = rawCall;
if (call == null) {
try {
// requestFactory根据args创建request对象
// 然后创建okhttp3.Call对象
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}

if (canceled) {
call.cancel();
}
// 使用okhttp3.Call对象进行请求,并将响应结果进行解析
return parseResponse(call.execute());
}

private okhttp3.Call createRawCall() throws IOException {
// requestFactory根据args创建request对象
// 然后根据request对象创建一个okhttp3.Call对象
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
// 返回okhttp3.Call对象
return call;
}

// 对响应进行解析
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 {
// 将响应体传入responseConverter对象也就是我们之前设置的GsonConverterFactory中去
// 将响应体转成对应的Java对象
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;
}
}
}
复制代码

同步请求的过程:

1、ExecutorCallbackCall通过调用excute方法,调用了传入的OkhttpCall对象的excute方法。
2、OkhttpCallexcute方法中,首先通过requestFactory根据args创建request对象,然后创建okhttp3.Call对象。
3、调用okhttp3.Callexcute方法,获取响应。
4、拿到响应后会根据响应码进行判断,通过判断后通过responseConverter对象将响应体转成对应的Java对象,并返回。

异步请求

关于异步请求的使用,在我们之前的举例中已经给出。

  static final class ExecutorCallbackCall<T> implements Call<T> {
// callbackExecutor属于MainThreadExecutor
final Executor callbackExecutor;
final Call<T> delegate;

// 异步请求
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
// 根据同步请求我们知道delegate就是一个OkhttpCall对象
// 调用OkhttpCall.exqueue方法执行异步请求
delegate.enqueue(new Callback<T>() {
// 获取响应的回调
@Override public void onResponse(Call<T> call, final Response<T> response) {
// 进行线程切换
// callbackExecutor就是MainThreadExecutor,其内部是通过主线程的Handler将Runnable发送到主线程去
// 从而达到切换线程的效果
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);
}
});
}
});
}
}
复制代码
final class OkHttpCall<T> implements Call<T> {

// 异步请求方法
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");

okhttp3.Call call;
Throwable failure;

synchronized (this) {
...
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
// 创建Call对象
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}

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

private okhttp3.Call createRawCall() throws IOException {
// requestFactory根据args创建一个request对象
// 将request对象分装成一个Call对象
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
复制代码

异步请求中有一个重要的操作就是将请求结果通过主线程的Handle发送到主线程去,从而达到线程切换的效果。

涉及的设计模式

在源码分析的过程中,我们能发现Retrofit中运用了大量的设置模式,这样做的好处就是将代码进行封装,方便我们调用。这里面用到的设计模式包括:构建者模式单例模式工厂模式代理模式外观模式装饰模式策略模式适配器模式
由于在之前的文章中已经提到了构建者模式单例模式工厂模式,所以这里不再多做陈述,但是我会给出它们在Retrofit中具体的出处。

1、构建者模式:最明显的就是在最初创建Retrofit对象时调用的new Retrofit.Builder().build()
2、单例模式:在Platform类中获取Plathform对象时使用的就是单例模式,有关单例的几种写法和它们之间的区别还希望大家能够有所了解。
3、工厂模式:最明显的是CallAdapter.FactoryConverter.Factory,但是工厂模式中又有:简单工厂抽象工厂工厂方法,需要区分开来。

代理模式

说到代理模式,有静态代理和动态代理之分。在Retrofit中我们最初接触的是动态代理。

public final class Retrofit {
...
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
...
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
...
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
...
}
});
}
...
}
复制代码

这里只有动态代理,那Retrofit中的静态代理在哪?在说静态代理之前要明白什么是静态代理:静态代理是指代理类在程序运行前已经存在的代理方式。

  static final class ExecutorCallbackCall<T> implements Call<T> {
...
// 这个delegate属于静态代理
final Call<T> 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()) {
...
} else {
...
}
}
});
}

@Override public void onFailure(Call<T> call, final Throwable t) {
...
}
});
}
}
复制代码

有关代理模式,在基础知识准备的时候已经给大家准备了几篇文章,这里就不再一一列出了。

外观模式

public interface ServiceApi {
@GET("wxarticle/chapters/json")
Call<Bean> getWxArtical();
}

ServiceApi serviceApi = retrofit.create(ServiceApi.class);
final Call<Bean> officialAccounts = serviceApi.getOfficialAccounts();
复制代码

我们在HTTP API接口中定义了很多方法,参数都在方法上进行定义,只会告诉调用者需要传入哪些参数,具体的操作并不向外暴露,这个就是外观设计模式。这里为到家准备了一篇设计模式之外观模式

装饰模式

允许向一个现有的对象添加新的功能,同时又不改变其结构。它是作为现有的类的一个包装。

  static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;

ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
...
}

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

delegate.enqueue(new Callback<T>() {
...
});
}
}
复制代码

我们可以将ExecutorCallbackCall看作是装饰类,但真正去执行请求的是OkHttpCall。之所以要有个装饰类,是希望做一些额外操作。这里的操作就是线程转换,将子线程切换到主线程上去。有关装饰设计模式,为大家准备了两篇文章: 设计模式之死磕装饰器模式(原创)装饰者模式

策略模式

简单的来说,策略模式就是做某些事情可能同时有多个方案,不同的时期使用不同的方案,怎样在调用的过程中尽可能的减少代码的修改,主要还是使用了Java中的多态。

public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {

Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
...
} else if (rawObservableType == Result.class) {
...
} else {
...
}
}
...
}
复制代码

RxJava2CallAdapterFactoryget方法中使用了策略模式,这里会根据rawObservableType的类型,作出对应的操作,如果感兴趣的小伙伴可以到源码里面看一下。
有关策略模式这里为大家准备了一篇文章:LOL设计模式之「策略模式」

适配器模式

我们在看Retrofit源码时,有可能在分析CallAdapter时被搞的晕头转向。如果从适配器的概念上来讲,就是将一个已经存在的东西,转成适合使用的东西。最常见的场景就是出国游玩的时候由于电源接口标准的不同,我们需要带一个转换头。
回头看Retrofit,如果我们一直时在Android上使用,那就需要通过静态代理ExecutorCallbackCall来切换线程,但是后来出现了新的技术Rxjava,感觉还挺好用的,不需要通过Handler进行线程切换了。这时就需要转换一下,将将OkHttpCall转换成rxjava(Scheduler)的写法,大概就是这么一个套路。
关于适配器模式,也给大家准备了一篇文章:《JAVA与模式》之适配器模式

总结

到这里我们已经把Retrofit的源码分析了一遍, 这里还是建议大家自己跟着源码走一遍,毕竟纸上得来终觉浅。最后还是那句话,本人是一名Android小学生,文中如有不妥之处还望各位不吝赐教,本人将不胜感激。