在使用 OkHttp 的时候,还是要自己构建 Request 的,我们的目的是请求一个 url 并拿到数据,构建流程不利于逻辑清晰,特别是当需要 Post 上传数据的时候。Square 显然是看到了这个问题,便推出了 Retrofit 来解决这个问题。
Retrofit 使用注解的方式来定义一个后端接口,在 运行时 解析,动态构建出请求逻辑并执行。有时候还是会遇上一些坑,所以最快捷的方式就是阅读它的源码,知道了内部逻辑,自然而然就知道了问题出在哪里。
这里基于 Retrofit:2.4.0-SNAPSHOT 分析
构建流程分析 Retrofit 简化请求的构建,使得网络请求就像简单的函数调用一样。这次就分析下面的案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 interface MyService { @GET("/user") Observable<User> getUser () ; } Retrofit retrofit = new Retrofit .Builder() .baseUrl("https://example.com/" ) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); MyService service = retrofit.create(MyService.class);Observable<User> observable = service.getUser();
请求流程概览 忽略前面 Retrofit 实例的配置和构建,直接分析后面的请求发起过程,下面是整个流程的概览图:
参照@stay4it 的流程图作了简化。
重要类剖析 ServiceMethod JavaDoc 中的注释是这样的:Adapts an invocation of an interface method into an HTTP call。大概意思就是把我们定义的接口方法包装成一个 HTTP 请求。在构建一个 ServiceMethod 实例时会解析我们定义的接口方法,解析注解以及返回值等等并确定 CallAdapter 和 Converter。
CallAdapter CallAdapter 是个接口,在 retrofit-calladapters 这个 module 下有它的实现类。这个类的作用是将一个 Call转换成一个 T,比如 Call-> Observable,从而直接拿到想要的类型值。
1 2 3 4 5 6 7 8 9 10 11 public interface CallAdapter <R, T> { Type responseType () ; T adapt (Call<R> call) ; abstract class Factory { public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); } }
Converter 请求/响应体转换,将实例转换成 HTTP 能接受的形式,或者从 HTTP 中转换出想要的类型。在 retrofit-converters 这个 Module 下有它的一些实现类,如 GsonXXXBodyConverter,它能实现 Call-> Call的转换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public interface Converter <F, T> { T convert (F value) throws IOException; abstract class Factory { public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null ; } public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null ; } public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null ; } } }
OkHttpCall 对 OkHttp 的Call 进行了一个包装,然后完成一些 Call 的操作,这里的 Call 是指 okhttp3.Call。