创建Retrofit实例
Retrofit采用构造者模式来创建实例。
new Retrofit.Builder()
        .client(okhttpClient)
        .baseUrl(baseUrl)
        .addConverterFactory(converterFactory)
        .addCallAdapterFactory(callAdapterFactory)
        .build();
Retrofit.Builder
Retrofit.Builder是Retrofit的静态类部类,它有以下属性
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;
platformplatform表示Retrofit当前运行的平台。它不能通过外部设置,只能由Retrofit自动识别。callFactorycallFactory表示网络请求器的工厂,主要作用是生成网络的请求器Call,一般情况下我们通过Builder#client()方法设置为OkHttpClient,当然,我们也可以通过Builder#callFactory()设置自定义工厂。baseUrlbaseUrl是我们网络请求中的基础Url,列如域名,一般情况下都是调用Builder#baseUrl(String)设置一个字符串,Retrofit会调用Retrofit#baseUrl(HttpUrl)方法自动转换成HttpUrl类型。converterFactories数据转换器列表,将请求到的数据转换成我们指定的类型。callAdapterFactories请求适配器列表,默认情况下我们得到的返回结果是Call<R>类型,通过自定义请求适配器,我们可以将结果转化为我们需要的类型,比如配合RxJava得到Observable<R>。callbackExecutor回调执行器,用于Call#enqueue()方法中,可实现线程切换,如果不指定,就会获取platform的defaultCallbackExecutor。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;
}
- 可以看到即使是从一个现有的Retrofit快速创建一个Builder,platform属性也是由Retrofit自动识别,然后初始化。
 - Retrofit在创建的时候会自动添加platform.defaultConverterFactories和BuiltIntConverters,所以这里复制的时候converterFactories就不需要再添加这两个了。
 - 对于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个重载方法,无论调用那个都需要满足下面两点
- baseUrl不能为null。
 - 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()方法主要执行了以下操作
- 检查baseUrl,如果为null直接抛出异常。
 - 检查网络请求器工厂callFactory,如果没有设置就默认使用OkHttpClient对象。
 - 检查回调执行器callbackExecutor,如果没有设置就默认使用当前platform提供的默认执行器,对于Android平台来说,使用的是MainThreadExecutor
 - 添加请求适配器,包括平台提供的和用户自定义的。
 - 添加数据转换器,包括BuiltInConverters和平台提供的以及用户自定义的。
 - 将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件事。
- 验证APIService
 - 利用动态代理生成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从以下方面进行检测
- APIService只能是一个接口类型。
 - APIService以及其继承的接口不能包含泛型参数。
 - 如果设置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执行了请求,它主要做了以下操作
- 判断请求是否执行过,如果执行过了就抛出异常。
 - 通过getRawCall()方法将retrofit2.Call转换成okhttp3.Call。
 - 通过okhttp3.Call执行请求。
 - 上一步执行请求返回的结果是okhttp3.Response,通过parseResponse()将okhttp3.Response转化为retrofit2.Response。
 
到这里Retrofit使用的主流程分析完了,对于Call和Response转换等源码将在后面进行分析。

京公网安备 11010502036488号