持续创造,加速成长!这是我参加「日新方案 6 月更文应战」的第22天,点击检查活动详情

创立Retrofit实例

Retrofit选用结构者形式来创立实例。

new Retrofit.Builder()
        .client(okhttpClient)
        .baseUrl(baseUrl)
        .addConverterFactory(converterFactory)
        .addCallAdapterFactory(callAdapterFactory)
        .build();

Retrofit.Builder

Retrofit.BuilderRetrofit的静态类部类,它有以下属性

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;
  • platform platform表明Retrofit当前运转的渠道。它不能经过外部设置,只能由Retrofit主动识别。
  • callFactory callFactory表明网络恳求器的工厂,首要作用是生成网络的恳求器Call,一般情况下咱们经过Builder#client()办法设置为OkHttpClient,当然,咱们也能够经过Builder#callFactory()设置自定义工厂。
  • baseUrl baseUrl是咱们网络恳求中的根底Url,列如域名,一般情况下都是调用Builder#baseUrl(String)设置一个字符串,Retrofit会调用Retrofit#baseUrl(HttpUrl)办法主动转化成HttpUrl类型。
  • converterFactories 数据转化器列表,将恳求到的数据转化成咱们指定的类型。
  • callAdapterFactories 恳求适配器列表,默许情况下咱们得到的回来成果是Call<R>类型,经过自定义恳求适配器,咱们能够将成果转化为咱们需求的类型,比如配合RxJava得到Observable<R>
  • callbackExecutor 回调履行器,用于Call#enqueue()办法中,可完成线程切换,假如不指定,就会获取platformdefaultCallbackExecutor
  • validateEagerly 是否提早对接口中的办法进行验证,假如Service声明的办法非常多,提早会集验证尽管能在早期就发现错误的办法,可是或许形成显着的功能损耗,所以一般在测验阶段设置为true确保即使发现问题,在正式环境中设置为false,这样接口中的办法就会分散验证,确保了功能问题。

创立Retrofit.Builder实例

Builder(Platform platform) {
}
public Builder() {
    this(Platform.get());
}
Builder(Retrofit retrofit) {
}

Retrofit.Builder供给了三个结构函数,可是暴露给外部调用的就只有无参结构函数,调用的时分会主动获取当前渠道类型,然后调用Builder(Platform platform)办法进行初始化,同时Retrofit也供给了快速仿制一个现有的Retrofit.Builder的办法。

public Builder newBuilder() {
    return new Builder(this);
}

经过调用Retrofit#newBuilder()办法,内部就会调用Builder(Retrofit retrofit)结构函数,从而快速创立一个Builder,详细仿制逻辑如下

Builder(Retrofit retrofit) {
	//1
    platform = Platform.get();
    callFactory = retrofit.callFactory;
    baseUrl = retrofit.baseUrl;
	//2
    for (int i = 1,
         size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
         i < size;
         i++) {
        converterFactories.add(retrofit.converterFactories.get(i));
    }
    //3
    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;
}
  1. 能够看到即使是从一个现有的Retrofit快速创立一个Builder,platform属性也是由Retrofit主动识别,然后初始化。
  2. Retrofit在创立的时分会主动增加platform.defaultConverterFactories和BuiltIntConverters,所以这儿仿制的时分converterFactories就不需求再增加这两个了。
  3. 关于callAdapterFactories的增加和converterFactories相似。

设置baseUrl

public Builder baseUrl(URL baseUrl) {
    Objects.requireNonNull(baseUrl, "baseUrl == null");
    return baseUrl(HttpUrl.get(baseUrl.toString()));
}
public Builder baseUrl(String baseUrl) {
    Objects.requireNonNull(baseUrl, "baseUrl == null");
    return baseUrl(HttpUrl.get(baseUrl));
}
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;
}

设置baseUrl有3个重载办法,无论调用那个都需求满意下面两点

  1. baseUrl不能为null。
  2. baseUrl必须以“/”结束。

生成Retrofit实例

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();
    }
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    List<Converter.Factory> converterFactories =
            new ArrayList<>(
                    1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());
    return new Retrofit(callFactory,baseUrl,unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories),callbackExecutor,validateEagerly);
}

build()办法首要履行了以下操作

  1. 检查baseUrl,假如为null直接抛出异常。
  2. 检查网络恳求器工厂callFactory,假如没有设置就默许运用OkHttpClient目标。
  3. 检查回调履行器callbackExecutor,假如没有设置就默许运用当前platform供给的默许履行器,关于Android渠道来说,运用的是MainThreadExecutor
  4. 增加恳求适配器,包括渠道供给的和用户自定义的。
  5. 增加数据转化器,包括BuiltInConverters和渠道供给的以及用户自定义的。
  6. 将converterFactories和callAdapterFactories转化成只读的List,然后创立Retrofit。

创立API接口实例

有了Retrofit实例之后,调用其create()办法获取API接口实例,在此之前,咱们先预备一个GitHubService

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

然后调用create()办法

GitHubService service = retrofit.create(GitHubService.class);

Retrofit.create()

create()办法完成比较简单,首要是运用动态代理生成传进来的API接口的实例。

public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
                service.getClassLoader(),
                new Class<?>[]{service},
                new InvocationHandler() {
				//省掉invoke()完成
                });
}

这儿首要做了2件事。

  1. 验证APIService
  2. 使用动态代理生成APIService实例。

验证APIService

接口验证

private void validateServiceInterface(Class<?> service) {
    if (!service.isInterface()) {
        throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    Deque<Class<?>> check = new ArrayDeque<>(1);
    check.add(service);
    while (!check.isEmpty()) {
        Class<?> candidate = check.removeFirst();
        if (candidate.getTypeParameters().length != 0) {
            throw new IllegalArgumentException(//......省掉异常);
        }
        Collections.addAll(check, candidate.getInterfaces());
    }
    if (validateEagerly) {
        //......省掉办法验证
    }
}

validateServiceInterface从以下方面进行检测

  1. APIService只能是一个接口类型。
  2. APIService以及其承继的接口不能包括泛型参数。
  3. 假如设置validateEagerly为true,就会立即对APIService中的办法进行检测,提早检测尽管能及时发现异常办法,可是会形成功能损耗。

办法验证

private void validateServiceInterface(Class<?> service) {
	//......省掉接口验证
    if (validateEagerly) {
        Platform platform = Platform.get();
        for (Method method : service.getDeclaredMethods()) {
            if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
                loadServiceMethod(method);
            }
        }
    }
}

能够看到,提早验证会跳过default办法和static润饰的办法。关于其他办法会调用loadServiceMethod()进行加载。

加载办法

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中,serviceMethodCache定义如下:

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

ConcurrentHashMap是线程安全的,假如serviceMethodCache中有当前method则直接取出回来,不然调用ServiceMethod.parseAnnotations()创立一个ServiceMethod,然后放入serviceMethodCache并回来成果。

ServiceMethod的parseAnnotations办法会创立ServiceMethod,这儿只暂时只重视主流程,就不深入检查。

Method.invoke()

public <T> T create(final Class<T> service) {
    //......省掉其他代码
    new InvocationHandler() {
        private final Platform platform = Platform.get();
        private final Object[] emptyArgs = new Object[0]; 
        public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)throws Throwable {
            if (method.getDeclaringClass() == Object.class) {
                return method.invoke(this, args);
            }
            args = args != null ? args : emptyArgs;
            return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
        }
}

首要,假如当前办法method来源于Object,则正常调用,关于其他办法,假如是default办规律交由渠道platform的invokeDefaultMethod()办法履行,不然将method转化成ServiceMethod然后履行。

履行恳求

经过前面咱们获取到了APIService的实例,然后经过它就能够调用详细办法,然后履行恳求

Call<List<Repo>> repos = service.listRepos("user").execute();

恳求的履行有同步和异步两种,这儿以同步为例

//OkHttpCall.java
public Response<T> execute() throws IOException {
	okhttp3.Call call;
	synchronized (this) {
	  if (executed) throw new IllegalStateException("Already executed.");
	  executed = true;
	  call = getRawCall();
	}
	if (canceled) {
	  call.cancel();
	}
	return parseResponse(call.execute());
}

能够看到Retrofit最后其实是调用来的OkHttp的Call履行了恳求,它首要做了以下操作

  1. 判别恳求是否履行过,假如履行过了就抛出异常。
  2. 经过getRawCall()办法将retrofit2.Call转化成okhttp3.Call。
  3. 经过okhttp3.Call履行恳求。
  4. 上一步履行恳求回来的成果是okhttp3.Response,经过parseResponse()将okhttp3.Response转化为retrofit2.Response。

到这儿Retrofit运用的主流程剖析完了,关于Call和Response转化等源码将在后边进行剖析。