我们知道,Retrofi的底层实际上是用OkHttp来进行网络请求的,本文也将会详细分析到OkHttp里面的调用链。
Retrofit基本用法
直接看官网https://square.github.io/retrofit/的例子。
首先创建一个GitHubService接口,这个接口定义了所有的网络请求。Repo是一个bean类,你可以在里面只定义一个String name;
的变量。
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
然后在我们的自己的类中,创建一个Retrofit对象,并调用Retrofit.create方法创建GitHubService的实例。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
接下来调用GitHubService的方法,得到Call对象的实例。通过这个Call的实例可以发起同步或者异步请求。
Call<List<Repo>> repos = service.listRepos("octocat");
发起异步请求。
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
Log.d("MainActivity", response.toString());
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
Log.d("MainActivity", t.toString());
}
});
调用流程源码解析
1. 创建Retrofit对象的实例
Retrofit实例创建使用了Builder模式。Builder的代码比较简单。主要看一下其构造函数。
Builder(Platform platform) {
this.platform = platform;//Retrofit既可以用于Android端,也可以用于Java平台。platform指的就是这两个平台。
}
public Builder() {
this(Platform.get());
}
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;//Call对象的创建工厂。
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));//变换器Converter列表。
}
// 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));//调用Service的方法返回的是Call对象如果不想要Call对象,例如与RxJava一起使用时,想要返回的是一个Observable对象,就通过传入一个RxJava的CallAdapter来实现。
}
callbackExecutor = retrofit.callbackExecutor;//调用Service方法后的回调。
validateEagerly = retrofit.validateEagerly;
}
2. Retrofit#create()方法
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
Retrofit#create()方法创建了一个GitHubService的代理类。
3. 调用GitHubService中的接口方法
调用GitHubService中的接口方法,其实执行的是代理类的invoke方法,也就是上面代码中InvocationHandler中override的invoke方法。我们先看一下loadServiceMethod(method)方法。
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
这个方法返回了一个ServiceMethod对象。ServiceMethod是一个抽象类。调用ServiceMethod.parseAnnotations得到真正的实现类HttpServiceMethod。
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);
}
实际执行HttpServiceMethod.parseAnnotations。这个parseAnnotations方法先通过CallAdapter拿到调用GitHubService要返回的类型,然后创建一个转换器Converter,将返回的数据流转换成目标类型。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
loadServiceMethod(method)方法拿到HttpServiceMethod的实例之后,就会执行其invoke方法。
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
Android7.0(Android SDK>=24)以上包括7.0,默认有两个CallAdapterFactory,一个是CompletableFutureCallAdapterFactory,一个是ExecutorCallAdapterFactory。Android7.0以下,只有一个ExecutorCallAdapterFactory。到底调用哪个CallAdapterFactory是根据我们在GitHubService中定义的方法的返回类型来确定的。
也就说,通过调用GitHubService接口的方法,一步一步到这里,调用的是ExecutorCallAdapterFactory/CompletableFutureCallAdapterFactory中生成的CallAdapter的adapt方法。
这里调用的是ExecutorCallAdapterFactory的adapt方法。
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
ExecutorCallAdapterFactory的adapt方法new 了一个ExecutorCallbackCall对象,直接return了。这个ExecutorCallbackCall实现了Call接口。后面我们执行call.enqueue操作时,实际就是执行的ExecutorCallbackCall里的enqueue方法。
整个前面这部分的思路可以说已经清晰了,简单总结一下:
调用Retrofit的create方法创建了我们定义请求的代理类,调用请求方法则是执行了CallAdapter的adapt方法,至于调用哪个CallAdapterFactory是根据定义请求接口的返回类型来选择的。默认会返回一个ExecutorCallbackCall对象。利用这个对象,我们可以发起同步或者异步请求。
由于篇幅太长,怕影响到阅读,后面发起请求部分的分析将放到下一篇来讲。