Retrofit的基本使用
- 创建描述查询信息的接口
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } - 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); - 通过retrofit实例的create方法创建接口的代理对象
GitHubService service = retrofit.create(GitHubService.class); - 调用接口方法, 返回Call对象
Call<List<Repo>> call = service.listRepos("111") // 返回Call对象之后步骤类似OkHttp, 调用Call的execute同步方法 // 或者enqueue异步方法并传递一个回调接口的实现 Call.enqueue(new CallBack<List<Repo>(){ onResponse() onFailure() })
Retrofit对象
-
Retrofit对象创建 (Builder建造者模式)
// 成员变量 // 缓解解析过的接口方法 ServiceMethod Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); okhttp3.Call.Factory callFactory; HttpUrl baseUrl; List<Converter.Factory> converterFactories; List<CallAdapter.Factory> callAdapterFactories; // 执行回调方法的执行器 Executor callbackExecutor; boolean validateEagerly; -
Retrofit.Builder
相比Retrofit类多出了一个Platform对象- 成员变量
// 平台对象 Platform platform; okhttp3.Call.Factory callFactory; HttpUrl baseUrl; List<Converter.Factory> converterFactories = new ArrayList<>(); List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); Executor callbackExecutor; boolean validateEagerly; - build方法
// 判断上面的成员变量是否为空, 为空则初始化一个默认的对象 // 列表类型的则添加一些内置的对象 // 最后通过这些成员遍历实例化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); }
- 成员变量
-
Platform
-
Android
Platform的内部类并集成Platform -
defaultCallbackExecutor() 方法返回回调的执行器
// Platform 的返回null Executor defaultCallbackExecutor() { return null; } // Android 的 返回一个主线程的 Executor public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } static final class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } }
-
-
Retrofit.create 方法
通过JDK动态代理创建接口的代理对象, 需要提供一个InvocationHandler对象实例, 最终方法都会进入其invoke方法。查看源码可知最终接口方法调用有2个主要步骤
1、loadServiceMethod(method) 返回一个ServiceMethod实例
2、调用ServiceMethod实例的invoke方法public @Nullable 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); } args = args != null ? args : emptyArgs; return platform.isDefaultMethod(method) ? platform.invokeDefaultMethod(method, service, proxy, args) : loadServiceMethod(method).invoke(args); } -
Retrofit.loadServiceMethod 方法
该方法的主要流程是去serviceMethodCache中查找, 如果找到直接返回, 没有找到则调用ServiceMethod.parseAnnotations进行解析
serviceMethodCache是Retrofit的成员变量, 主要用来缓存解析过的接口方法ServiceMethodServiceMethod<?> 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
1、是个抽象类
2、提供一个 parseAnnotations 的静态方法来解析接口方法
3、提供一个 invoke 抽象方法对 ServiceMethod 进行调用
abstract class ServiceMethod<T> {
// 解析接口方法为 ServiceMethod
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1) 解析接口方法的注解
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
// 省略一些异常处理代码
// 2) 根据第一步的解析构造具体的 ServiceMethod 实现类
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
// invoke 调用方法
abstract @Nullable T invoke(Object[] args);
}
RequestFactory
用于生成Request的工厂
- 成员变量
private final Method method; // 方法 (是那个接口方法的工厂) private final HttpUrl baseUrl; // base url final String httpMethod; // 请求方法 private final @Nullable String relativeUrl; // 相对url private final @Nullable Headers headers; // 请求头 private final @Nullable MediaType contentType; private final boolean hasBody; private final boolean isFormEncoded; private final boolean isMultipart; private final ParameterHandler<?>[] parameterHandlers; final boolean isKotlinSuspendFunction; // 是否是kotlin的suspend方法 - parseAnnotations 静态方法
// 通过内部的Builder创建 RequestFactory 实例 static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } // Builder的构造方法 // 获取方法的注解和参数的注解 Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; // 方法对应的注解 this.methodAnnotations = method.getAnnotations(); // 方法的参数类型 this.parameterTypes = method.getGenericParameterTypes(); // 方法的参数对应的注解 this.parameterAnnotationsArray = method.getParameterAnnotations(); } // build() 中会具体进行解析(代码比较长久不贴了)
HttpServiceMethod
1、ServiceMethod的子类
2、本身还是一个抽象类
3、提供 parseAnnotations 静态方法, 最终生成一个具体的ServiceMethod 实现类对象
-
parseAnnotations 静态方法
主要工作是根据前一步解析的情况来创建一个HttpServiceMethod类型的实现类返回
1、创建 CallAdapter
2、创建 Converter
3、创建 HttpServiceMethod 实现类, 需要用到1和2的结果作为参数static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { // 是否为kotlin suspend 方法 boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; // 协程是否要返回Response boolean continuationWantsResponse = false; boolean continuationBodyNullable = false; // 省略 针对 isKotlinSuspendFunction 的情况进行相应处理 // 创建一个 CallAdapter 实例 CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); // 省略一些检查的工作 // 创建一个 Converter 实例 Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { // 不是Kotlin suspend方法 return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { // 是kotlin suspend 方法, 并且期望返回 Response return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>( requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); } else { // 是kotlin suspend 方法, 只需要Body return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>( requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable); } } -
invoke方法
上面提到loadServiceMethod返回ServiceMethod实例后会调用invoke方法, 而ServiceMethod的invoke是抽象方法, 具体逻辑在HttpServiceMethod实现, 可以看到HttpServiceMethod构造了一个OkHttpCall对象然后 调用了adapt方法。
其实HttpServiceMethod类的adapt也是一个抽象方法// HttpServiceMethod 的 invoke final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
CallAdapted
上文提到HttpServiceMethod的adapter为抽象方法, 在 HttpServiceMethod 类中以内部类的方式提供了三个具体子类, 其中2个和Kotlin 协程相关, 这里只解释非协程的那一个。
从源码可以看到 adapt 最后调用了 CallAdapter 的 adapter 方法, 这个CallAdapter是在构造函数中传递的。 从前面 HttpServiceMethod 的 parseAnnotations 可以看到该对象的创建过程。
1、HttpServiceMethod 的实现类
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
// CallAdapter 对象
private final CallAdapter<ResponseT, ReturnT> callAdapter;
// 构造方法
// 需要 RequestFactory 、okhttp3.Call.Factory、 Converter、CallAdapter
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
// adapter方法, 直接调用 callAdapter 的 adapter方法
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
CallAdapter
1、接口
2、debug发现上面提到的CallAdapter实例对象从 DefaultCallAdapterFactory 中返回
- DefaultCallAdapterFactory
get 方法会返回一个匿名的CallAdapter对象public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } else if (!(returnType instanceof ParameterizedType)) { throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>"); } else { final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType)returnType); final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : this.callbackExecutor; // 返回一个匿名 CallAdapter 的对象 return new CallAdapter<Object, Call<?>>() { public Type responseType() { return responseType; } // adapter 方法 // Call是在 HttpServiceMethod 中创建的OkHttpCall对象 // 所以Adapter方法返回的是一个 public Call<Object> adapt(Call<Object> call) { // 如果回调的执行器为空则直接返回原来的 OkHttpCall 对象 // 否则返回 ExecutorCallbackCall 对象 return (Call)(executor == null ? call : new DefaultCallAdapterFactory.ExecutorCallbackCall(executor, call)); } }; } }
OkHttpCall
OkHttpCall 是 Retrofit 的一层封装, 里面包含一个 rawCall 成员, 这个成员才是 OKHttp 框架中的 Call, 最终对应的实现类为 OkHttp 中的 RealCall, 通过这个 rawCall 就能发起 OkHttp 层面的网络请求
private @Nullable okhttp3.Call rawCall;
-
enqueue(final Callback callback) 方法
1、获取到 rawCall 对象, 实际为 RealCall
2、调用 rawCall 的 enqueue 方法, 并提供一个 CallBack
3、在内层 CallBack 的 onResponse 中调用 parseResponse 对结果进行进一步处理, 包括使用 convert 将返回数据类型转换成 Java 对象
4、在外层 CallBack 中 回调用户提供的逻辑
Callback
enqueue执行任务时可以带一个回调接口
-
OkHttp 的回调
OkHttp的回调包装在AsyncCall中, 是一个Runnable类型, 在线程池中调用, 执行在子线程 -
Retrofit的回调
Retrofit通过 OkHttpCall 执行enqueue, OkHttpCall 会被进一步包装成ExecutorCallbackCall, 其中包含一个回调执行器和一个代理对象(OkHttpCall本身), 请求被分发给代理, 回调在回调执行器中执行 -
MainThreadExecutor
上面提到的回调执行器, 持有一个和UI线程相关的Handler, 把Callback的内容包装成 Runnable 交给handler分发到主线程。所以Retrofit中的回调默认在主线程中执行。static final class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } }
ExecutorCallbackCall
继承Call接口, 内部封装了一个回调执行器和一个Call代理对象。
static final class ExecutorCallbackCall<T> implements Call<T> {
-
回调执行器
回调执行器默认在Retrofit.Builder的 build 中创建(也可以创建Retrofit对象的时候自己指定一个) -
回调执行器默认创建
Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { // platform 在 Android 平台实际为 Plotform 的内部类 Android callbackExecutor = platform.defaultCallbackExecutor(); } // 返回 MainThreadExecutor public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } static final class MainThreadExecutor implements Executor { // 包含主线程Looper的Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } -
Call代理
Call代理其实就是对传入的 OkHttpCall对象的引用, 请求的发起仍然通过 OkHttpCall 来完成 (OkHttpCall进一步通过 OkHttp框架的 RealCall来完成)。